@hardfin/cli 0.1.0-dev.30 → 0.1.0-dev.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -3
- package/dist/cli.js +4 -4
- package/dist/completion-tree.json +120 -0
- package/dist/{program-BZW_50HP.js → program-B02z-kNH.js} +106 -39
- package/dist/{scrub-VtQmxap1.js → scrub-BN3gyBpR.js} +23 -14
- package/dist/{sentry-D5lKx0nm.js → sentry-CLaeAWNa.js} +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,15 @@ hardfin file get file_7hq2mx9pkr4stz8w --output photo.jpg
|
|
|
77
77
|
hardfin file get file_7hq2mx9pkr4stz8w --output - | wc -c
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
Send a whole body as JSON with `--input`, from a file or from standard input. A flag given as
|
|
81
|
+
well replaces its field, and a required field the body carries needs no flag. A value with a
|
|
82
|
+
comma in it, which a `key=value` flag cannot carry, goes through `--input`.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
hardfin location create --input location.json
|
|
86
|
+
echo '{"name": "Dock 4, north side"}' | hardfin location create --input -
|
|
87
|
+
```
|
|
88
|
+
|
|
80
89
|
Clear a field with `--unset`, naming the flag:
|
|
81
90
|
|
|
82
91
|
```sh
|
|
@@ -159,8 +168,18 @@ hardfin status # what the CLI is configured with and signed in as
|
|
|
159
168
|
hardfin logout # forget this machine, and ask Hardfin to revoke it
|
|
160
169
|
```
|
|
161
170
|
|
|
162
|
-
An API key is still the way to run unattended. `HARDFIN_API_KEY
|
|
163
|
-
so CI and an agent sandbox need no browser.
|
|
171
|
+
An API key is still the way to run unattended. `--api-key`, or `HARDFIN_API_KEY`, wins over
|
|
172
|
+
a stored sign in, so CI and an agent sandbox need no browser. The flag beats the variable.
|
|
173
|
+
|
|
174
|
+
An API key is held to two rules before it is sent:
|
|
175
|
+
|
|
176
|
+
| Rule | Why |
|
|
177
|
+
| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
178
|
+
| It goes only over https, or to this machine | Anything between here and the host could read it |
|
|
179
|
+
| A key you set, by flag or exported variable, never goes to an API URL that `config.local.json` or `.env` in the working directory chose | A repository you cloned could otherwise send your key to its own server |
|
|
180
|
+
|
|
181
|
+
A key and an API URL that come from the same folder's files still work together, which is
|
|
182
|
+
how a local build is set up. Pass `--api-url` to send a key you set to that folder's address.
|
|
164
183
|
|
|
165
184
|
### What login does
|
|
166
185
|
|
|
@@ -373,7 +392,7 @@ settings, and the one nearest the top wins.
|
|
|
373
392
|
|
|
374
393
|
| Layer | Where | Beats |
|
|
375
394
|
| ----------- | --------------------------------------------------------------------- | ---------------- |
|
|
376
|
-
| Flag | `--api-url`
|
|
395
|
+
| Flag | `--api-url`, `--api-key`, `--issuer-url` | everything below |
|
|
377
396
|
| Environment | an exported `HARDFIN_*` variable | the files below |
|
|
378
397
|
| Env file | `.env` in the working directory, or the file `HARDFIN_ENV_FILE` names | the config file |
|
|
379
398
|
| Config file | `config.local.json` in the working directory | the defaults |
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="62437fed-ab84-53c5-9984-9bbadc0f2e15")}catch(e){}}();
|
|
4
4
|
import module from "node:module";
|
|
5
5
|
//#region src/cli.ts
|
|
6
6
|
module.enableCompileCache?.();
|
|
@@ -14,7 +14,7 @@ process.on("unhandledRejection", (error) => void toCrash(error));
|
|
|
14
14
|
try {
|
|
15
15
|
const answer = await toQuickAnswer(process.argv.slice(2));
|
|
16
16
|
if (answer === void 0) {
|
|
17
|
-
const { toCli, toParseExitCode, wasReportAttempted } = await import("./program-
|
|
17
|
+
const { toCli, toParseExitCode, wasReportAttempted } = await import("./program-B02z-kNH.js");
|
|
18
18
|
try {
|
|
19
19
|
await toCli().parseAsync(process.argv);
|
|
20
20
|
} catch (error) {
|
|
@@ -33,7 +33,7 @@ async function toCrash(error) {
|
|
|
33
33
|
isCrashing = true;
|
|
34
34
|
process.stderr.write(`error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
35
35
|
try {
|
|
36
|
-
const { toReported } = await import("./program-
|
|
36
|
+
const { toReported } = await import("./program-B02z-kNH.js");
|
|
37
37
|
await toReported(error, false, void 0, "fatal");
|
|
38
38
|
} finally {
|
|
39
39
|
process.exit(1);
|
|
@@ -51,4 +51,4 @@ async function toQuickAnswer(args) {
|
|
|
51
51
|
export {};
|
|
52
52
|
|
|
53
53
|
//# sourceMappingURL=cli.js.map
|
|
54
|
-
//# debugId=
|
|
54
|
+
//# debugId=62437fed-ab84-53c5-9984-9bbadc0f2e15
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
"description": "The API to call, whose host also holds the authorization server",
|
|
6
6
|
"valueName": "url"
|
|
7
7
|
},
|
|
8
|
+
{
|
|
9
|
+
"name": "api-key",
|
|
10
|
+
"description": "An API key to call with, in place of HARDFIN_API_KEY or a sign in",
|
|
11
|
+
"valueName": "key"
|
|
12
|
+
},
|
|
8
13
|
{
|
|
9
14
|
"name": "issuer-url",
|
|
10
15
|
"description": "The authorization server, when it does not sit at the API's host",
|
|
@@ -346,6 +351,11 @@
|
|
|
346
351
|
"valueName": "field",
|
|
347
352
|
"repeatable": true
|
|
348
353
|
},
|
|
354
|
+
{
|
|
355
|
+
"name": "input",
|
|
356
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
357
|
+
"valueName": "path"
|
|
358
|
+
},
|
|
349
359
|
{
|
|
350
360
|
"name": "json",
|
|
351
361
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -379,6 +389,11 @@
|
|
|
379
389
|
"valueName": "assetId=,deliverAt=,deliverAtTimezone=,destinationId=,originId=,shipAt=,shipAtTimezone=",
|
|
380
390
|
"repeatable": true
|
|
381
391
|
},
|
|
392
|
+
{
|
|
393
|
+
"name": "input",
|
|
394
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
395
|
+
"valueName": "path"
|
|
396
|
+
},
|
|
382
397
|
{
|
|
383
398
|
"name": "json",
|
|
384
399
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -407,6 +422,11 @@
|
|
|
407
422
|
"valueName": "assetId=,deliverAt=,id=,shipAt=",
|
|
408
423
|
"repeatable": true
|
|
409
424
|
},
|
|
425
|
+
{
|
|
426
|
+
"name": "input",
|
|
427
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
428
|
+
"valueName": "path"
|
|
429
|
+
},
|
|
410
430
|
{
|
|
411
431
|
"name": "json",
|
|
412
432
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -482,6 +502,11 @@
|
|
|
482
502
|
"valueName": "field",
|
|
483
503
|
"repeatable": true
|
|
484
504
|
},
|
|
505
|
+
{
|
|
506
|
+
"name": "input",
|
|
507
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
508
|
+
"valueName": "path"
|
|
509
|
+
},
|
|
485
510
|
{
|
|
486
511
|
"name": "json",
|
|
487
512
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -591,6 +616,11 @@
|
|
|
591
616
|
"valueName": "field",
|
|
592
617
|
"repeatable": true
|
|
593
618
|
},
|
|
619
|
+
{
|
|
620
|
+
"name": "input",
|
|
621
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
622
|
+
"valueName": "path"
|
|
623
|
+
},
|
|
594
624
|
{
|
|
595
625
|
"name": "json",
|
|
596
626
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -618,6 +648,11 @@
|
|
|
618
648
|
"description": "Whether Hardfin sets the asset's in-service date itself",
|
|
619
649
|
"negatable": true
|
|
620
650
|
},
|
|
651
|
+
{
|
|
652
|
+
"name": "input",
|
|
653
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
654
|
+
"valueName": "path"
|
|
655
|
+
},
|
|
621
656
|
{
|
|
622
657
|
"name": "json",
|
|
623
658
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -690,6 +725,11 @@
|
|
|
690
725
|
"valueName": "field",
|
|
691
726
|
"repeatable": true
|
|
692
727
|
},
|
|
728
|
+
{
|
|
729
|
+
"name": "input",
|
|
730
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
731
|
+
"valueName": "path"
|
|
732
|
+
},
|
|
693
733
|
{
|
|
694
734
|
"name": "json",
|
|
695
735
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -888,6 +928,11 @@
|
|
|
888
928
|
"valueName": "field",
|
|
889
929
|
"repeatable": true
|
|
890
930
|
},
|
|
931
|
+
{
|
|
932
|
+
"name": "input",
|
|
933
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
934
|
+
"valueName": "path"
|
|
935
|
+
},
|
|
891
936
|
{
|
|
892
937
|
"name": "json",
|
|
893
938
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -908,6 +953,11 @@
|
|
|
908
953
|
"description": "The day your organization takes the asset back, which cannot be in the future",
|
|
909
954
|
"valueName": "value"
|
|
910
955
|
},
|
|
956
|
+
{
|
|
957
|
+
"name": "input",
|
|
958
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
959
|
+
"valueName": "path"
|
|
960
|
+
},
|
|
911
961
|
{
|
|
912
962
|
"name": "json",
|
|
913
963
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -960,6 +1010,11 @@
|
|
|
960
1010
|
"valueName": "field",
|
|
961
1011
|
"repeatable": true
|
|
962
1012
|
},
|
|
1013
|
+
{
|
|
1014
|
+
"name": "input",
|
|
1015
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1016
|
+
"valueName": "path"
|
|
1017
|
+
},
|
|
963
1018
|
{
|
|
964
1019
|
"name": "json",
|
|
965
1020
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1022,6 +1077,11 @@
|
|
|
1022
1077
|
"valueName": "field",
|
|
1023
1078
|
"repeatable": true
|
|
1024
1079
|
},
|
|
1080
|
+
{
|
|
1081
|
+
"name": "input",
|
|
1082
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1083
|
+
"valueName": "path"
|
|
1084
|
+
},
|
|
1025
1085
|
{
|
|
1026
1086
|
"name": "json",
|
|
1027
1087
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1101,6 +1161,11 @@
|
|
|
1101
1161
|
"valueName": "field",
|
|
1102
1162
|
"repeatable": true
|
|
1103
1163
|
},
|
|
1164
|
+
{
|
|
1165
|
+
"name": "input",
|
|
1166
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1167
|
+
"valueName": "path"
|
|
1168
|
+
},
|
|
1104
1169
|
{
|
|
1105
1170
|
"name": "json",
|
|
1106
1171
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1160,6 +1225,11 @@
|
|
|
1160
1225
|
"valueName": "field",
|
|
1161
1226
|
"repeatable": true
|
|
1162
1227
|
},
|
|
1228
|
+
{
|
|
1229
|
+
"name": "input",
|
|
1230
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1231
|
+
"valueName": "path"
|
|
1232
|
+
},
|
|
1163
1233
|
{
|
|
1164
1234
|
"name": "json",
|
|
1165
1235
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1308,6 +1378,11 @@
|
|
|
1308
1378
|
"valueName": "field",
|
|
1309
1379
|
"repeatable": true
|
|
1310
1380
|
},
|
|
1381
|
+
{
|
|
1382
|
+
"name": "input",
|
|
1383
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1384
|
+
"valueName": "path"
|
|
1385
|
+
},
|
|
1311
1386
|
{
|
|
1312
1387
|
"name": "json",
|
|
1313
1388
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1397,6 +1472,11 @@
|
|
|
1397
1472
|
"valueName": "field",
|
|
1398
1473
|
"repeatable": true
|
|
1399
1474
|
},
|
|
1475
|
+
{
|
|
1476
|
+
"name": "input",
|
|
1477
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1478
|
+
"valueName": "path"
|
|
1479
|
+
},
|
|
1400
1480
|
{
|
|
1401
1481
|
"name": "json",
|
|
1402
1482
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1659,6 +1739,11 @@
|
|
|
1659
1739
|
"valueName": "field",
|
|
1660
1740
|
"repeatable": true
|
|
1661
1741
|
},
|
|
1742
|
+
{
|
|
1743
|
+
"name": "input",
|
|
1744
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1745
|
+
"valueName": "path"
|
|
1746
|
+
},
|
|
1662
1747
|
{
|
|
1663
1748
|
"name": "json",
|
|
1664
1749
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1734,6 +1819,11 @@
|
|
|
1734
1819
|
"valueName": "field",
|
|
1735
1820
|
"repeatable": true
|
|
1736
1821
|
},
|
|
1822
|
+
{
|
|
1823
|
+
"name": "input",
|
|
1824
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1825
|
+
"valueName": "path"
|
|
1826
|
+
},
|
|
1737
1827
|
{
|
|
1738
1828
|
"name": "json",
|
|
1739
1829
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1833,6 +1923,11 @@
|
|
|
1833
1923
|
"valueName": "field",
|
|
1834
1924
|
"repeatable": true
|
|
1835
1925
|
},
|
|
1926
|
+
{
|
|
1927
|
+
"name": "input",
|
|
1928
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1929
|
+
"valueName": "path"
|
|
1930
|
+
},
|
|
1836
1931
|
{
|
|
1837
1932
|
"name": "json",
|
|
1838
1933
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1893,6 +1988,11 @@
|
|
|
1893
1988
|
"valueName": "field",
|
|
1894
1989
|
"repeatable": true
|
|
1895
1990
|
},
|
|
1991
|
+
{
|
|
1992
|
+
"name": "input",
|
|
1993
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
1994
|
+
"valueName": "path"
|
|
1995
|
+
},
|
|
1896
1996
|
{
|
|
1897
1997
|
"name": "json",
|
|
1898
1998
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1919,6 +2019,11 @@
|
|
|
1919
2019
|
"valueName": "field",
|
|
1920
2020
|
"repeatable": true
|
|
1921
2021
|
},
|
|
2022
|
+
{
|
|
2023
|
+
"name": "input",
|
|
2024
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
2025
|
+
"valueName": "path"
|
|
2026
|
+
},
|
|
1922
2027
|
{
|
|
1923
2028
|
"name": "json",
|
|
1924
2029
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -2136,6 +2241,11 @@
|
|
|
2136
2241
|
"valueName": "field",
|
|
2137
2242
|
"repeatable": true
|
|
2138
2243
|
},
|
|
2244
|
+
{
|
|
2245
|
+
"name": "input",
|
|
2246
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
2247
|
+
"valueName": "path"
|
|
2248
|
+
},
|
|
2139
2249
|
{
|
|
2140
2250
|
"name": "json",
|
|
2141
2251
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -2255,6 +2365,11 @@
|
|
|
2255
2365
|
"valueName": "field",
|
|
2256
2366
|
"repeatable": true
|
|
2257
2367
|
},
|
|
2368
|
+
{
|
|
2369
|
+
"name": "input",
|
|
2370
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
2371
|
+
"valueName": "path"
|
|
2372
|
+
},
|
|
2258
2373
|
{
|
|
2259
2374
|
"name": "json",
|
|
2260
2375
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -2366,6 +2481,11 @@
|
|
|
2366
2481
|
"valueName": "field",
|
|
2367
2482
|
"repeatable": true
|
|
2368
2483
|
},
|
|
2484
|
+
{
|
|
2485
|
+
"name": "input",
|
|
2486
|
+
"description": "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
2487
|
+
"valueName": "path"
|
|
2488
|
+
},
|
|
2369
2489
|
{
|
|
2370
2490
|
"name": "json",
|
|
2371
2491
|
"description": "Print machine-readable output, which is the default when stdout is not a terminal"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
4
|
-
import { a as defineCommand, i as GLOBAL_FLAGS, r as ExitCode, t as toInvocation } from "./scrub-
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b1928379-e7e3-5a7e-9ade-d45695e05814")}catch(e){}}();
|
|
4
|
+
import { a as defineCommand, i as GLOBAL_FLAGS, r as ExitCode, t as toInvocation } from "./scrub-BN3gyBpR.js";
|
|
5
5
|
import { n as toCompletion, t as toAnswer$1 } from "./completion-tree-rR_Rmeij.js";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { Command, CommanderError, Option } from "commander";
|
|
@@ -694,12 +694,15 @@ const held = /* @__PURE__ */ new Map();
|
|
|
694
694
|
* unattended caller sets it deliberately, and otherwise the stored refresh token buys an
|
|
695
695
|
* access token that lives only in memory.
|
|
696
696
|
*/
|
|
697
|
-
async function toRequestCredential(settings) {
|
|
698
|
-
if (settings.apiKey)
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
697
|
+
async function toRequestCredential(settings, sources) {
|
|
698
|
+
if (settings.apiKey) {
|
|
699
|
+
refuseForeignKey(settings, sources);
|
|
700
|
+
return {
|
|
701
|
+
header: "X-API-Key",
|
|
702
|
+
value: settings.apiKey,
|
|
703
|
+
kind: "api key"
|
|
704
|
+
};
|
|
705
|
+
}
|
|
703
706
|
refuseForeignHost(settings);
|
|
704
707
|
const stored = toCredential(settings.issuerUrl);
|
|
705
708
|
if (!stored) throw new NoCredential("not authenticated. Run hardfin login, or set HARDFIN_API_KEY");
|
|
@@ -775,6 +778,20 @@ function refuseForeignHost(settings) {
|
|
|
775
778
|
if (api.host !== issuer.host) throw new NoCredential(`this sign in belongs to ${issuer.host}, so it is not sent to ${api.host}. Set HARDFIN_API_KEY to call another host, or point --issuer-url at the server that signs you in`);
|
|
776
779
|
if (api.protocol !== "https:" && !isLoopback(api.hostname)) throw new NoCredential(`${settings.apiUrl} is not https, so a sign in is not sent to it`);
|
|
777
780
|
}
|
|
781
|
+
/** The layers a file in the working directory sets, which a cloned repository can carry. */
|
|
782
|
+
const DIRECTORY_SOURCES = /* @__PURE__ */ new Set(["config file", "env file"]);
|
|
783
|
+
/** refuseForeignKey keeps an API key off plain connections and off hosts a stray file chose. */
|
|
784
|
+
function refuseForeignKey(settings, sources) {
|
|
785
|
+
const api = toHost$1(settings.apiUrl);
|
|
786
|
+
if (api === void 0) throw new NoCredential(`${settings.apiUrl} is not a URL this CLI can call`);
|
|
787
|
+
if (api.protocol !== "https:" && !isLoopback(api.hostname)) throw new NoCredential(`Your API key was not sent, because ${api.host} does not use a secure connection.`);
|
|
788
|
+
const isKeyChosen = sources?.apiKey !== void 0 && !DIRECTORY_SOURCES.has(sources.apiKey);
|
|
789
|
+
const isUrlFromFolder = sources?.apiUrl !== void 0 && DIRECTORY_SOURCES.has(sources.apiUrl);
|
|
790
|
+
if (isKeyChosen && isUrlFromFolder) {
|
|
791
|
+
const file = sources.apiUrl === "config file" ? CONFIG_FILE : ".env";
|
|
792
|
+
throw new NoCredential(`Your API key was not sent to ${api.host}, because that address comes from a file in this folder, not from you.\nDetails: the API URL is set in ${file}. Pass --api-url to use it anyway`);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
778
795
|
function toHost$1(url) {
|
|
779
796
|
try {
|
|
780
797
|
return new URL(url);
|
|
@@ -790,12 +807,15 @@ function isLoopback(hostname) {
|
|
|
790
807
|
* an access token this process already holds. An error report uses it, because a refresh
|
|
791
808
|
* cut short by the process ending would spend the refresh token and sign the person out.
|
|
792
809
|
*/
|
|
793
|
-
function toHeldCredential(settings) {
|
|
794
|
-
if (settings.apiKey)
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
810
|
+
function toHeldCredential(settings, sources) {
|
|
811
|
+
if (settings.apiKey) {
|
|
812
|
+
refuseForeignKey(settings, sources);
|
|
813
|
+
return {
|
|
814
|
+
header: "X-API-Key",
|
|
815
|
+
value: settings.apiKey,
|
|
816
|
+
kind: "api key"
|
|
817
|
+
};
|
|
818
|
+
}
|
|
799
819
|
const current = held.get(settings.issuerUrl);
|
|
800
820
|
if (!current || (current.expiresAt ?? 0) - EXPIRY_MARGIN_MS <= Date.now()) return;
|
|
801
821
|
return {
|
|
@@ -966,7 +986,7 @@ function toGuide(commands, version) {
|
|
|
966
986
|
"",
|
|
967
987
|
"## Before calling",
|
|
968
988
|
"",
|
|
969
|
-
"- Authenticate by setting `HARDFIN_API_KEY`, or by running `hardfin login`",
|
|
989
|
+
"- Authenticate with `--api-key`, by setting `HARDFIN_API_KEY`, or by running `hardfin login`",
|
|
970
990
|
"- Every command prints JSON on stdout and diagnostics on stderr",
|
|
971
991
|
"- Output is JSON whenever stdout is not a terminal, so no flag is needed when calling from code",
|
|
972
992
|
"",
|
|
@@ -1045,6 +1065,31 @@ function toSummary(command) {
|
|
|
1045
1065
|
subcommands: command.subcommands?.filter((entry) => !entry.hidden).map(toSummary)
|
|
1046
1066
|
};
|
|
1047
1067
|
}
|
|
1068
|
+
//#endregion
|
|
1069
|
+
//#region src/command/input.ts
|
|
1070
|
+
/** InputFailure is a body given with --input that cannot be used, and says why. */
|
|
1071
|
+
var InputFailure = class extends Error {
|
|
1072
|
+
constructor(message) {
|
|
1073
|
+
super(message);
|
|
1074
|
+
this.name = "InputFailure";
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
/** toJSONInput reads the JSON a command was given with --input, from a file or from standard input. */
|
|
1078
|
+
function toJSONInput(source) {
|
|
1079
|
+
const name = source === "-" ? "standard input" : source;
|
|
1080
|
+
let text;
|
|
1081
|
+
try {
|
|
1082
|
+
text = readFileSync(source === "-" ? 0 : source, "utf8");
|
|
1083
|
+
} catch {
|
|
1084
|
+
return new InputFailure(`${name} cannot be read`);
|
|
1085
|
+
}
|
|
1086
|
+
if (text.trim() === "") return new InputFailure(`${name} is empty, and a body needs JSON`);
|
|
1087
|
+
try {
|
|
1088
|
+
return JSON.parse(text);
|
|
1089
|
+
} catch {
|
|
1090
|
+
return new InputFailure(`${name} does not hold JSON`);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1048
1093
|
const apiCommand = defineCommand({
|
|
1049
1094
|
name: "api",
|
|
1050
1095
|
summary: "Call a Hardfin API endpoint and print what it answers",
|
|
@@ -1122,16 +1167,16 @@ async function runApi(input) {
|
|
|
1122
1167
|
}
|
|
1123
1168
|
let body;
|
|
1124
1169
|
if (typeof input.flags["input"] === "string") {
|
|
1125
|
-
body =
|
|
1126
|
-
if (body
|
|
1127
|
-
writeFailure("invalid_input",
|
|
1170
|
+
body = toJSONInput(input.flags["input"]);
|
|
1171
|
+
if (body instanceof InputFailure) {
|
|
1172
|
+
writeFailure("invalid_input", body.message, input.isJSON);
|
|
1128
1173
|
return ExitCode.USAGE;
|
|
1129
1174
|
}
|
|
1130
1175
|
}
|
|
1131
1176
|
try {
|
|
1132
1177
|
writeData((await request$1({
|
|
1133
1178
|
apiUrl: input.resolved.settings.apiUrl,
|
|
1134
|
-
credential: await toRequestCredential(input.resolved.settings),
|
|
1179
|
+
credential: await toRequestCredential(input.resolved.settings, input.resolved.sources),
|
|
1135
1180
|
method: toText(input.flags["method"] ?? "GET").toUpperCase(),
|
|
1136
1181
|
path,
|
|
1137
1182
|
query,
|
|
@@ -1160,14 +1205,6 @@ function toQuery$1(fields) {
|
|
|
1160
1205
|
}
|
|
1161
1206
|
return query;
|
|
1162
1207
|
}
|
|
1163
|
-
function toBody$1(source) {
|
|
1164
|
-
const text = source === "-" ? readFileSync(0, "utf8") : readFileSync(source, "utf8");
|
|
1165
|
-
try {
|
|
1166
|
-
return JSON.parse(text);
|
|
1167
|
-
} catch {
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
1208
|
//#endregion
|
|
1172
1209
|
//#region src/auth/browser.ts
|
|
1173
1210
|
/** isWSL reports whether this Linux is running under Windows. */
|
|
@@ -2543,7 +2580,7 @@ function toServerReport(metadata) {
|
|
|
2543
2580
|
async function toApiReport(resolved, options) {
|
|
2544
2581
|
const settings = resolved.settings;
|
|
2545
2582
|
try {
|
|
2546
|
-
const credential = options.isHeldOnly ? toHeldCredential(settings) : await toRequestCredential(settings);
|
|
2583
|
+
const credential = options.isHeldOnly ? toHeldCredential(settings, resolved.sources) : await toRequestCredential(settings, resolved.sources);
|
|
2547
2584
|
if (!credential) return {
|
|
2548
2585
|
checked: false,
|
|
2549
2586
|
url: settings.apiUrl,
|
|
@@ -2675,7 +2712,7 @@ async function report(error, occasion, resolved) {
|
|
|
2675
2712
|
const settings = resolved ?? toResolved();
|
|
2676
2713
|
const status = settings ? await toStatus(settings) : void 0;
|
|
2677
2714
|
const secrets = [settings?.settings.apiKey, settings ? toCredential(settings.settings.issuerUrl)?.refreshToken : void 0];
|
|
2678
|
-
return await (await import("./sentry-
|
|
2715
|
+
return await (await import("./sentry-CLaeAWNa.js")).send({
|
|
2679
2716
|
error,
|
|
2680
2717
|
occasion,
|
|
2681
2718
|
telemetry,
|
|
@@ -2867,7 +2904,7 @@ const REFUSED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
2867
2904
|
"mcp"
|
|
2868
2905
|
]);
|
|
2869
2906
|
/** The global options, which sit before a command and take a value of their own. */
|
|
2870
|
-
const GLOBAL_OPTIONS_WITH_VALUES =
|
|
2907
|
+
const GLOBAL_OPTIONS_WITH_VALUES = new Set(GLOBAL_FLAGS.filter((flag) => flag.valueName).map((flag) => `--${flag.name}`));
|
|
2871
2908
|
/**
|
|
2872
2909
|
* toCommandName reads which command a call names. A global option sits before it, so
|
|
2873
2910
|
* reading the first argument alone would let --issuer-url x logout through.
|
|
@@ -3077,6 +3114,12 @@ const UNSET_FLAG = {
|
|
|
3077
3114
|
repeatable: true,
|
|
3078
3115
|
schema: z.array(z.string())
|
|
3079
3116
|
};
|
|
3117
|
+
const INPUT_FLAG = {
|
|
3118
|
+
name: "input",
|
|
3119
|
+
description: "A file holding the JSON request body, or - for standard input. A flag given as well replaces its field",
|
|
3120
|
+
valueName: "path",
|
|
3121
|
+
schema: z.string()
|
|
3122
|
+
};
|
|
3080
3123
|
const FILE_FLAG = {
|
|
3081
3124
|
name: "file",
|
|
3082
3125
|
description: "The file to upload",
|
|
@@ -3100,6 +3143,7 @@ function defineOperation(operation) {
|
|
|
3100
3143
|
...operation.queryFlags,
|
|
3101
3144
|
...operation.bodyFlags,
|
|
3102
3145
|
...operation.bodyFlags.some((flag) => flag.nullable) ? [UNSET_FLAG] : [],
|
|
3146
|
+
...operation.bodyFlags.length > 0 ? [INPUT_FLAG] : [],
|
|
3103
3147
|
...operation.upload ? [...operation.upload.fields, FILE_FLAG] : [],
|
|
3104
3148
|
...operation.downloads ? [OUTPUT_FLAG] : [],
|
|
3105
3149
|
JSON_FLAG
|
|
@@ -3127,12 +3171,17 @@ async function runOperation(operation, input) {
|
|
|
3127
3171
|
writeFailure("invalid_arguments", `this command takes ${operation.pathParameters.length} argument(s)`, input.isJSON);
|
|
3128
3172
|
return ExitCode.USAGE;
|
|
3129
3173
|
}
|
|
3130
|
-
const
|
|
3174
|
+
const given = toGivenBody(input.flags["input"]);
|
|
3175
|
+
if (given instanceof InputFailure) {
|
|
3176
|
+
writeFailure("invalid_input", given.message, input.isJSON);
|
|
3177
|
+
return ExitCode.USAGE;
|
|
3178
|
+
}
|
|
3179
|
+
const missing = operation.bodyFlags.concat(operation.upload?.fields ?? []).filter((flag) => flag.required && input.flags[toOptionKey(flag.name)] === void 0 && !hasPath(given, flag.jsonPath));
|
|
3131
3180
|
if (missing.length > 0) {
|
|
3132
3181
|
writeFailure("missing_flag", `this command needs ${missing.map((flag) => `--${flag.name}`).join(", ")}`, input.isJSON);
|
|
3133
3182
|
return ExitCode.USAGE;
|
|
3134
3183
|
}
|
|
3135
|
-
const body = toBody(operation, input.flags);
|
|
3184
|
+
const body = toBody(operation, input.flags, given);
|
|
3136
3185
|
if (body instanceof Error) {
|
|
3137
3186
|
writeFailure("invalid_flag", body.message, input.isJSON);
|
|
3138
3187
|
return ExitCode.USAGE;
|
|
@@ -3153,7 +3202,7 @@ async function runOperation(operation, input) {
|
|
|
3153
3202
|
try {
|
|
3154
3203
|
const envelope = await request$1({
|
|
3155
3204
|
apiUrl: input.resolved.settings.apiUrl,
|
|
3156
|
-
credential: await toRequestCredential(input.resolved.settings),
|
|
3205
|
+
credential: await toRequestCredential(input.resolved.settings, input.resolved.sources),
|
|
3157
3206
|
method: operation.method,
|
|
3158
3207
|
path,
|
|
3159
3208
|
query: toQuery(operation, input.flags),
|
|
@@ -3241,10 +3290,27 @@ async function toForm(upload, flags) {
|
|
|
3241
3290
|
}
|
|
3242
3291
|
return form;
|
|
3243
3292
|
}
|
|
3244
|
-
/**
|
|
3245
|
-
function
|
|
3246
|
-
|
|
3247
|
-
|
|
3293
|
+
/** toGivenBody reads the --input body, which a generated command takes only as a JSON object. */
|
|
3294
|
+
function toGivenBody(source) {
|
|
3295
|
+
if (typeof source !== "string") return;
|
|
3296
|
+
const read = toJSONInput(source);
|
|
3297
|
+
if (read instanceof InputFailure) return read;
|
|
3298
|
+
if (typeof read !== "object" || read === null || Array.isArray(read)) return new InputFailure(`the body in ${source === "-" ? "standard input" : source} must be a JSON object, such as {"name": "Acme"}`);
|
|
3299
|
+
return read;
|
|
3300
|
+
}
|
|
3301
|
+
/** hasPath reports whether a body already holds a value at a field's path. */
|
|
3302
|
+
function hasPath(body, path) {
|
|
3303
|
+
let holder = body;
|
|
3304
|
+
for (const name of path) {
|
|
3305
|
+
if (typeof holder !== "object" || holder === null || !(name in holder)) return false;
|
|
3306
|
+
holder = holder[name];
|
|
3307
|
+
}
|
|
3308
|
+
return true;
|
|
3309
|
+
}
|
|
3310
|
+
/** toBody builds the request body from the --input body and the flags, a flag winning over its field. */
|
|
3311
|
+
function toBody(operation, flags, given) {
|
|
3312
|
+
const body = given ? structuredClone(given) : {};
|
|
3313
|
+
let hasField = given !== void 0;
|
|
3248
3314
|
for (const flag of operation.bodyFlags) {
|
|
3249
3315
|
const value = flags[toOptionKey(flag.name)];
|
|
3250
3316
|
if (value === void 0) continue;
|
|
@@ -6060,6 +6126,7 @@ async function toExitCode(root, command, args, flags) {
|
|
|
6060
6126
|
try {
|
|
6061
6127
|
resolved = toSettings({
|
|
6062
6128
|
apiUrl: root.opts()["apiUrl"],
|
|
6129
|
+
apiKey: root.opts()["apiKey"],
|
|
6063
6130
|
issuerUrl: root.opts()["issuerUrl"]
|
|
6064
6131
|
});
|
|
6065
6132
|
return await command.run?.({
|
|
@@ -6101,5 +6168,5 @@ async function toReported(error, isJSON, resolved, level = "error") {
|
|
|
6101
6168
|
//#endregion
|
|
6102
6169
|
export { toCli, toParseExitCode, toReported, wasReportAttempted };
|
|
6103
6170
|
|
|
6104
|
-
//# sourceMappingURL=program-
|
|
6105
|
-
//# debugId=
|
|
6171
|
+
//# sourceMappingURL=program-B02z-kNH.js.map
|
|
6172
|
+
//# debugId=b1928379-e7e3-5a7e-9ade-d45695e05814
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3af5060a-b6fe-5f2e-9661-01f4460a7b04")}catch(e){}}();
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
//#region src/command/registry.ts
|
|
@@ -17,17 +17,26 @@ function defineCommand(command) {
|
|
|
17
17
|
return command;
|
|
18
18
|
}
|
|
19
19
|
/** GLOBAL_FLAGS are the options the CLI takes before any command. */
|
|
20
|
-
const GLOBAL_FLAGS = [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
const GLOBAL_FLAGS = [
|
|
21
|
+
{
|
|
22
|
+
name: "api-url",
|
|
23
|
+
description: "The API to call, whose host also holds the authorization server",
|
|
24
|
+
valueName: "url",
|
|
25
|
+
schema: z.string()
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "api-key",
|
|
29
|
+
description: "An API key to call with, in place of HARDFIN_API_KEY or a sign in",
|
|
30
|
+
valueName: "key",
|
|
31
|
+
schema: z.string()
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "issuer-url",
|
|
35
|
+
description: "The authorization server, when it does not sit at the API's host",
|
|
36
|
+
valueName: "url",
|
|
37
|
+
schema: z.string()
|
|
38
|
+
}
|
|
39
|
+
];
|
|
31
40
|
//#endregion
|
|
32
41
|
//#region src/report/scrub.ts
|
|
33
42
|
const REDACTED = "[redacted]";
|
|
@@ -109,5 +118,5 @@ function toFlag(flags, word) {
|
|
|
109
118
|
//#endregion
|
|
110
119
|
export { defineCommand as a, GLOBAL_FLAGS as i, toScrubbed as n, ExitCode as r, toInvocation as t };
|
|
111
120
|
|
|
112
|
-
//# sourceMappingURL=scrub-
|
|
113
|
-
//# debugId=
|
|
121
|
+
//# sourceMappingURL=scrub-BN3gyBpR.js.map
|
|
122
|
+
//# debugId=3af5060a-b6fe-5f2e-9661-01f4460a7b04
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
4
|
-
import { n as toScrubbed } from "./scrub-
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="853940c3-9e72-566b-ad70-9f043e6aba8d")}catch(e){}}();
|
|
4
|
+
import { n as toScrubbed } from "./scrub-BN3gyBpR.js";
|
|
5
5
|
import { dirname } from "node:path";
|
|
6
6
|
import { request } from "node:http";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
@@ -4385,5 +4385,5 @@ function toTags(delivery) {
|
|
|
4385
4385
|
//#endregion
|
|
4386
4386
|
export { send };
|
|
4387
4387
|
|
|
4388
|
-
//# sourceMappingURL=sentry-
|
|
4389
|
-
//# debugId=
|
|
4388
|
+
//# sourceMappingURL=sentry-CLaeAWNa.js.map
|
|
4389
|
+
//# debugId=853940c3-9e72-566b-ad70-9f043e6aba8d
|