@maschinenlesbar.org/bundeshaushalt-cli 0.0.1 → 0.0.3
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 +142 -135
- package/dist/src/cli/commands/budget.d.ts.map +1 -1
- package/dist/src/cli/commands/budget.js +13 -8
- package/dist/src/cli/commands/budget.js.map +1 -1
- package/dist/src/cli/program.d.ts.map +1 -1
- package/dist/src/cli/program.js +5 -1
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/cli/shared.d.ts.map +1 -1
- package/dist/src/cli/shared.js +8 -1
- package/dist/src/cli/shared.js.map +1 -1
- package/dist/src/client/engine.d.ts +10 -1
- package/dist/src/client/engine.d.ts.map +1 -1
- package/dist/src/client/engine.js +67 -7
- package/dist/src/client/engine.js.map +1 -1
- package/dist/src/client/http.d.ts.map +1 -1
- package/dist/src/client/http.js +103 -14
- package/dist/src/client/http.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,192 +1,199 @@
|
|
|
1
1
|
# bundeshaushalt-cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
3
|
+
[](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/release.yml)
|
|
5
|
+
[](https://www.npmjs.com/package/@maschinenlesbar.org/bundeshaushalt-cli)
|
|
6
|
+
|
|
7
|
+
Query the German federal budget from your terminal. `bundeshaushalt` is a
|
|
8
|
+
small command-line tool over the open
|
|
9
|
+
[bundeshaushalt.de](https://bundeshaushalt.de/) budget-data portal: fetch
|
|
10
|
+
expenses and income by year, drill into individual budget items, economic
|
|
11
|
+
groups or functional areas, and compare planned vs. realised figures — as
|
|
12
|
+
clean JSON you can pipe straight into [`jq`](https://jqlang.github.io/jq/).
|
|
13
|
+
|
|
14
|
+
- **Works out of the box** — no account, no API key, no configuration. Install and query.
|
|
15
|
+
- **Clean JSON output** — pretty-printed by default, `--compact` for one-line/scripting.
|
|
16
|
+
- **Three commands** — `budget`, `expenses`, and `income` (the last two are convenient shortcuts).
|
|
17
|
+
- **Nothing to configure** — the endpoint is public and unauthenticated; nothing to leak.
|
|
18
|
+
- **Data from 2012 onward** — planned and realised figures, every budget year the portal has published.
|
|
19
|
+
|
|
20
|
+
> **Note.** The tool calls an *undocumented internal endpoint* of the portal
|
|
21
|
+
> (`/internalapi/budgetData`). It is not a published, stable public API and can
|
|
22
|
+
> change or disappear without notice. Treat it as best-effort.
|
|
23
|
+
|
|
24
|
+
> Want to use this as a TypeScript library or understand how it's built?
|
|
25
|
+
> See **[DEVELOPING.md](DEVELOPING.md)**.
|
|
17
26
|
|
|
18
27
|
## Install
|
|
19
28
|
|
|
20
29
|
```bash
|
|
21
|
-
npm
|
|
22
|
-
npm run build # compiles TypeScript to dist/
|
|
30
|
+
npm i -g @maschinenlesbar.org/bundeshaushalt-cli
|
|
23
31
|
```
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
This installs the **`bundeshaushalt`** command. Requires **Node.js 20+**.
|
|
34
|
+
|
|
35
|
+
Check it works:
|
|
26
36
|
|
|
27
37
|
```bash
|
|
28
|
-
node dist/src/cli/index.js --help
|
|
29
|
-
# or, after `npm link` / global install:
|
|
30
38
|
bundeshaushalt --help
|
|
31
39
|
```
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
## How the data is shaped
|
|
41
|
+
## Quickstart
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
No setup needed — the endpoint requires no key. Your first query:
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
```bash
|
|
46
|
+
bundeshaushalt expenses 2024
|
|
47
|
+
```
|
|
42
48
|
|
|
43
|
-
The
|
|
44
|
-
|
|
49
|
+
The result is a JSON object. The top-level breakdown lives under `children`;
|
|
50
|
+
summary metadata is in `meta`. Pull out just the children with `jq`:
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
> rate-limit, or disappear **without notice**. The data is served without
|
|
50
|
-
> authentication and currently covers years from `2012` onward (the exact upper
|
|
51
|
-
> range depends on what the portal has published). Treat this dependency as
|
|
52
|
-
> best-effort, especially for any production or commercial use.
|
|
52
|
+
```bash
|
|
53
|
+
bundeshaushalt expenses 2024 | jq '.children[] | {id, label, value}'
|
|
54
|
+
```
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
Drill into one budget item by taking an `id` from those results:
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
| `--timeout <ms>` | Per-request timeout (default `30000`) |
|
|
60
|
-
| `--user-agent <ua>` | `User-Agent` header value |
|
|
61
|
-
| `--max-retries <n>` | Retries for transient `429`/`503` responses (default `2`) |
|
|
62
|
-
| `--max-response-bytes <n>` | Cap response body size in bytes (`0` = unlimited; default 100 MiB) |
|
|
63
|
-
| `--compact` | Print JSON on a single line |
|
|
64
|
-
|
|
65
|
-
Global options may appear **before or after** the command, e.g. both
|
|
66
|
-
`bundeshaushalt --compact expenses 2024` and `bundeshaushalt expenses 2024 --compact`
|
|
67
|
-
work (they are resolved with commander's `optsWithGlobals`).
|
|
58
|
+
```bash
|
|
59
|
+
bundeshaushalt budget 2024 expenses --id 090168301
|
|
60
|
+
```
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
## Commands
|
|
70
63
|
|
|
71
64
|
```text
|
|
72
|
-
budget
|
|
73
|
-
expenses
|
|
74
|
-
income
|
|
65
|
+
budget <year> <account> [options] federal budget data for a year and account side
|
|
66
|
+
expenses <year> [options] shortcut for: budget <year> expenses
|
|
67
|
+
income <year> [options] shortcut for: budget <year> income
|
|
75
68
|
```
|
|
76
69
|
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
`<year>` is a four-digit year between `2012` and the current year (inclusive).
|
|
71
|
+
`<account>` is `expenses` or `income`.
|
|
72
|
+
|
|
73
|
+
### Command options
|
|
74
|
+
|
|
75
|
+
These apply to `budget`, `expenses`, and `income`:
|
|
76
|
+
|
|
77
|
+
| Option | Values | Description |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `--quota <quota>` | `target` \| `actual` | Planned (`target`, default) vs. realised (`actual`) figures |
|
|
80
|
+
| `--unit <unit>` | `single` \| `function` \| `group` | Grouping — budget item (default), functional area, or economic group |
|
|
81
|
+
| `--id <id>` | budget number | Drill into one element; `G-` prefix for groups, `F-` for functions |
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
## Common tasks
|
|
84
|
+
|
|
85
|
+
A few recipes to get going — see **[Usage.md](Usage.md)** for the full,
|
|
86
|
+
use-case-driven set.
|
|
81
87
|
|
|
82
88
|
```bash
|
|
83
89
|
# Top-level federal expenses for 2024
|
|
84
90
|
bundeshaushalt expenses 2024
|
|
85
91
|
|
|
86
|
-
# Realised
|
|
87
|
-
bundeshaushalt
|
|
92
|
+
# Realised (actual) expenses — compare with planned (target, the default)
|
|
93
|
+
bundeshaushalt expenses 2023 --quota actual
|
|
88
94
|
|
|
89
|
-
#
|
|
95
|
+
# Break expenses down by economic group (Gruppe)
|
|
90
96
|
bundeshaushalt budget 2024 expenses --unit group
|
|
91
97
|
|
|
92
|
-
#
|
|
93
|
-
bundeshaushalt budget 2024 expenses --
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Exit codes: `0` success, `4` on a `404` from the API, `1` for any other error, non-zero for usage errors.
|
|
98
|
+
# Break expenses down by functional area (Funktion)
|
|
99
|
+
bundeshaushalt budget 2024 expenses --unit function
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
# Drill into one budget item by id
|
|
102
|
+
bundeshaushalt budget 2024 expenses --id 090168301
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
# Drill into an economic group (G- prefix)
|
|
105
|
+
bundeshaushalt budget 2024 expenses --unit group --id G-5
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
# Look at a historical year
|
|
108
|
+
bundeshaushalt expenses 2015 --quota actual
|
|
109
|
+
```
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
## Output & scripting
|
|
106
112
|
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
Every command prints **pretty JSON to stdout**. Errors and diagnostics go to
|
|
114
|
+
stderr, so piping stdout into `jq` stays clean.
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
```bash
|
|
117
|
+
# Compare planned vs. realised headline totals for 2023
|
|
118
|
+
bundeshaushalt expenses 2023 --quota target --compact | jq '.detail.value'
|
|
119
|
+
bundeshaushalt expenses 2023 --quota actual --compact | jq '.detail.value'
|
|
111
120
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (err instanceof HaushaltApiError) console.error(err.status, err.detail);
|
|
116
|
-
}
|
|
117
|
-
```
|
|
121
|
+
# List all top-level budget items as a tab-separated table
|
|
122
|
+
bundeshaushalt expenses 2024 \
|
|
123
|
+
| jq -r '.children[] | "\(.id)\t\(.label)\t\(.value)"'
|
|
118
124
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
new BundeshaushaltClient({
|
|
123
|
-
baseUrl: "https://bundeshaushalt.de",
|
|
124
|
-
timeoutMs: 15_000,
|
|
125
|
-
maxRetries: 3, // 429 / 503 are retried with linear backoff
|
|
126
|
-
maxResponseBytes: 50 << 20, // abort responses larger than 50 MiB (0 = unlimited)
|
|
127
|
-
userAgent: "my-app/1.0",
|
|
128
|
-
transport: customTransport, // inject your own HTTP transport
|
|
129
|
-
});
|
|
125
|
+
# How many children does a query return?
|
|
126
|
+
bundeshaushalt expenses 2024 | jq '.children | length'
|
|
130
127
|
```
|
|
131
128
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`client.budgetData({ year, account, quota?, unit?, id? })`. The `AccountValues` /
|
|
135
|
-
`QuotaValues` / `UnitValues` enums are exported for reference.
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Architecture
|
|
129
|
+
Use `--compact` for single-line JSON in pipelines and logs:
|
|
140
130
|
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
client/
|
|
144
|
-
enums.ts # Account / Quota / Unit value sets + MIN_YEAR
|
|
145
|
-
types.ts # BudgetData / BudgetElement / BudgetMeta + param object
|
|
146
|
-
query.ts # dependency-free query-string builder
|
|
147
|
-
http.ts # the Transport interface + default node:http/https transport
|
|
148
|
-
engine.ts # URL building, retry/backoff, redirects, JSON decoding, error mapping
|
|
149
|
-
errors.ts # HaushaltError / HaushaltApiError / HaushaltNetworkError / HaushaltParseError
|
|
150
|
-
client.ts # BundeshaushaltClient — the budget-data surface over the engine
|
|
151
|
-
cli/
|
|
152
|
-
io.ts # injectable I/O seam (stdout/stderr/file)
|
|
153
|
-
shared.ts # option parsers, global-option resolver, JSON renderer
|
|
154
|
-
commands/ # budget + expenses/income shortcuts
|
|
155
|
-
program.ts # assembles the commander program from injectable deps
|
|
156
|
-
run.ts # parses argv -> exit code (no process.exit; testable)
|
|
157
|
-
index.ts # #! bin shim
|
|
131
|
+
```bash
|
|
132
|
+
bundeshaushalt --compact expenses 2024 | jq -c '.children[]'
|
|
158
133
|
```
|
|
159
134
|
|
|
160
|
-
**
|
|
135
|
+
`--compact` (and every global option) works **before or after** the command —
|
|
136
|
+
both `bundeshaushalt --compact expenses 2024` and `bundeshaushalt expenses 2024 --compact`
|
|
137
|
+
do the same thing.
|
|
161
138
|
|
|
162
|
-
|
|
163
|
-
uses `node:http`/`node:https`; tests inject a mock. This keeps the client free of any HTTP framework.
|
|
164
|
-
- The CLI is built around injectable `CliDeps` (client factory + I/O), so the whole program can be
|
|
165
|
-
driven in-process by tests with a mocked client and captured output — no subprocesses.
|
|
166
|
-
- `account`/`quota`/`unit` are validated against their enums and the year is range-checked before any request.
|
|
139
|
+
**Exit codes** make the CLI easy to use in scripts:
|
|
167
140
|
|
|
168
|
-
|
|
141
|
+
| Code | Meaning |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `0` | success (also `--help` / `--version`) |
|
|
144
|
+
| `4` | budget item not found (`404`) |
|
|
145
|
+
| `1` | any other error — including bad usage / invalid arguments |
|
|
146
|
+
|
|
147
|
+
## Troubleshooting
|
|
148
|
+
|
|
149
|
+
- **`command not found: bundeshaushalt`** — the global npm bin directory isn't
|
|
150
|
+
on your `PATH`. Run `npm bin -g` to find it and add it, or run via
|
|
151
|
+
`npx @maschinenlesbar.org/bundeshaushalt-cli …`.
|
|
152
|
+
- **Exit `4` / "not found"** — the budget item id doesn't exist for the
|
|
153
|
+
requested year/account/unit combination. Re-fetch a fresh list to pick a
|
|
154
|
+
valid id.
|
|
155
|
+
- **Year out of range** — the CLI validates years locally; it only accepts
|
|
156
|
+
`2012` through the current calendar year. Out-of-range years are rejected
|
|
157
|
+
before any network request is made.
|
|
158
|
+
- **Network error / exit `1`** — connectivity, DNS, or a timeout. Try again,
|
|
159
|
+
or raise the limit with `--timeout 60000`. The client retries `429`/`503`
|
|
160
|
+
responses automatically (default 2 retries).
|
|
161
|
+
- **Empty or unexpected results** — this tool calls an undocumented internal
|
|
162
|
+
endpoint that can change shape without notice. If results look wrong, check
|
|
163
|
+
whether the portal itself has changed.
|
|
164
|
+
|
|
165
|
+
## Global options
|
|
166
|
+
|
|
167
|
+
These apply to every command and may be given before *or* after it:
|
|
169
168
|
|
|
170
|
-
|
|
169
|
+
| Option | Description |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `-V, --version` | Print the version number |
|
|
172
|
+
| `-h, --help` | Show help for the program or a command |
|
|
173
|
+
| `--compact` | Print JSON on a single line instead of pretty-printed |
|
|
174
|
+
| `--base-url <url>` | API base URL (default `https://bundeshaushalt.de`) |
|
|
175
|
+
| `--timeout <ms>` | Per-request timeout in milliseconds (default `30000`) |
|
|
176
|
+
| `--user-agent <ua>` | `User-Agent` header value |
|
|
177
|
+
| `--max-retries <n>` | Retries for transient `429`/`503` responses (default `2`) |
|
|
178
|
+
| `--max-response-bytes <n>` | Cap response body size in bytes (`0` = unlimited; default 100 MiB) |
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
npm test # builds, then runs `node --test` over dist/test
|
|
174
|
-
```
|
|
180
|
+
## Learn more
|
|
175
181
|
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
182
|
+
- **[Usage.md](Usage.md)** — full use-case-driven cookbook.
|
|
183
|
+
- **[GLOSSARY.md](GLOSSARY.md)** — every term and domain concept explained.
|
|
184
|
+
- **[DEVELOPING.md](DEVELOPING.md)** — TypeScript library usage, architecture, testing, CI.
|
|
185
|
+
- **[SKILLS.md](SKILLS.md)** — Claude Code Agent Skills bundled with this repo (ministry
|
|
186
|
+
breakdown, plan-vs-actual comparison, multi-year trends), installable as a plugin.
|
|
181
187
|
|
|
182
|
-
##
|
|
188
|
+
## Data license
|
|
183
189
|
|
|
184
|
-
|
|
190
|
+
This CLI is a **client** — it accesses data it does not own or redistribute. The
|
|
191
|
+
upstream data is © its provider and licensed **separately from this tool's code**.
|
|
192
|
+
See **[DATA_LICENSE.md](DATA_LICENSE.md)**.
|
|
185
193
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
- **docs.yml** — build TypeDoc API docs and deploy to GitHub Pages on each `v*` tag.
|
|
194
|
+
> **Bundesministerium der Finanzen** — public data without copyright protection on
|
|
195
|
+
> bundeshaushalt.de (amtliches Werk); free to reuse incl. commercially, source
|
|
196
|
+
> credit recommended. (The parallel BMF Datenportal / GovData channel is `dl-de/by-2-0`.)
|
|
190
197
|
|
|
191
198
|
## License
|
|
192
199
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAsFxC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAiC5E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Option } from "commander";
|
|
1
2
|
import { action, assertEnum, renderJson } from "../shared.js";
|
|
2
3
|
import { HaushaltError } from "../../client/errors.js";
|
|
3
4
|
import { AccountValues, QuotaValues, UnitValues, MIN_YEAR } from "../../client/enums.js";
|
|
@@ -29,12 +30,12 @@ function requireYear(value) {
|
|
|
29
30
|
/** Build the optional quota/unit/id params shared by all budget commands. */
|
|
30
31
|
function optionsFrom(opts) {
|
|
31
32
|
const params = {};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
// --quota / --unit are validated by commander's .choices() (see
|
|
34
|
+
// addBudgetOptions), so they are already one of the allowed values here.
|
|
35
|
+
if (opts["quota"] !== undefined)
|
|
36
|
+
params.quota = opts["quota"];
|
|
37
|
+
if (opts["unit"] !== undefined)
|
|
38
|
+
params.unit = opts["unit"];
|
|
38
39
|
if (opts["id"] !== undefined) {
|
|
39
40
|
const raw = String(opts["id"]);
|
|
40
41
|
// A value that looks like an option flag (e.g. `--id --quota`) is almost
|
|
@@ -60,8 +61,12 @@ function optionsFrom(opts) {
|
|
|
60
61
|
}
|
|
61
62
|
function addBudgetOptions(cmd) {
|
|
62
63
|
return cmd
|
|
63
|
-
.
|
|
64
|
-
|
|
64
|
+
.addOption(new Option("--quota <quota>", "planned vs realised (default target)").choices([
|
|
65
|
+
...QuotaValues,
|
|
66
|
+
]))
|
|
67
|
+
.addOption(new Option("--unit <unit>", "how elements are grouped (default single)").choices([
|
|
68
|
+
...UnitValues,
|
|
69
|
+
]))
|
|
65
70
|
.option("--id <id>", 'budget number id ("G-" prefix for groups, "F-" for functions)');
|
|
66
71
|
}
|
|
67
72
|
export function registerBudgetCommands(program, deps) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../../src/cli/commands/budget.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../../src/cli/commands/budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA4BvC,eAAO,MAAM,OAAO,QAAgB,CAAC;AAErC,yEAAyE;AACzE,eAAO,MAAM,WAAW,EAAE,OAGzB,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,GAAE,OAAqB,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA4BvC,eAAO,MAAM,OAAO,QAAgB,CAAC;AAErC,yEAAyE;AACzE,eAAO,MAAM,WAAW,EAAE,OAGzB,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,GAAE,OAAqB,GAAG,OAAO,CAgCjE"}
|
package/dist/src/cli/program.js
CHANGED
|
@@ -40,12 +40,16 @@ export function buildProgram(deps = defaultDeps) {
|
|
|
40
40
|
program
|
|
41
41
|
.name("bundeshaushalt")
|
|
42
42
|
.description("CLI for the open German federal budget API (https://bundeshaushalt.de)")
|
|
43
|
+
// The global options genuinely apply after a subcommand, so surface them in
|
|
44
|
+
// every subcommand's --help (as a "Global Options:" section) rather than only
|
|
45
|
+
// on the root, matching the docs' promise that they apply to every command.
|
|
46
|
+
.configureHelp({ showGlobalOptions: true })
|
|
43
47
|
.version(VERSION)
|
|
44
48
|
.option("--base-url <url>", "API base URL", "https://bundeshaushalt.de")
|
|
45
49
|
.option("--timeout <ms>", "per-request timeout in milliseconds", parseIntArg, 30_000)
|
|
46
50
|
.option("--user-agent <ua>", "User-Agent header value")
|
|
47
51
|
.option("--max-retries <n>", "retries for transient 429/503 responses", parseBoundedIntArg(MAX_RETRIES_LIMIT), 2)
|
|
48
|
-
.option("--max-response-bytes <n>", "cap response body size in bytes (0 = unlimited;
|
|
52
|
+
.option("--max-response-bytes <n>", "cap response body size in bytes (0 = unlimited; 100 MiB)", parseIntArg, 100 * 1024 * 1024)
|
|
49
53
|
.option("--compact", "print JSON on a single line instead of pretty-printed")
|
|
50
54
|
.showHelpAfterError();
|
|
51
55
|
registerBudgetCommands(program, deps);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.js","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,4EAA4E;AAC5E,mBAAmB;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;;GAKG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC5F,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAErC,yEAAyE;AACzE,MAAM,CAAC,MAAM,WAAW,GAAY;IAClC,EAAE,EAAE,SAAS;IACb,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAC,OAAO,CAAC;CAC7D,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,OAAgB,WAAW;IACtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,gBAAgB,CAAC;SACtB,WAAW,CAAC,wEAAwE,CAAC;
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,4EAA4E;AAC5E,mBAAmB;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;;GAKG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC5F,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAErC,yEAAyE;AACzE,MAAM,CAAC,MAAM,WAAW,GAAY;IAClC,EAAE,EAAE,SAAS;IACb,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAC,OAAO,CAAC;CAC7D,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,OAAgB,WAAW;IACtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,gBAAgB,CAAC;SACtB,WAAW,CAAC,wEAAwE,CAAC;QACtF,4EAA4E;QAC5E,8EAA8E;QAC9E,4EAA4E;SAC3E,aAAa,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;SAC1C,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,kBAAkB,EAAE,cAAc,EAAE,2BAA2B,CAAC;SACvE,MAAM,CAAC,gBAAgB,EAAE,qCAAqC,EAAE,WAAW,EAAE,MAAM,CAAC;SACpF,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CACL,mBAAmB,EACnB,yCAAyC,EACzC,kBAAkB,CAAC,iBAAiB,CAAC,EACrC,CAAC,CACF;SACA,MAAM,CACL,0BAA0B,EAC1B,0DAA0D,EAC1D,WAAW,EACX,GAAG,GAAG,IAAI,GAAG,IAAI,CAClB;SACA,MAAM,CAAC,WAAW,EAAE,uDAAuD,CAAC;SAC5E,kBAAkB,EAAE,CAAC;IAExB,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAEtC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAQzE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,OAAO,EAAE,MAAM,GACd,CAAC,CAKH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAQpE;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGrF;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IAC5C,MAAM,EAAE,aAAa,CAAC;IACtB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAQvC"}
|
package/dist/src/cli/shared.js
CHANGED
|
@@ -14,7 +14,14 @@ export function parseIntArg(value) {
|
|
|
14
14
|
if (!/^\d+$/.test(value)) {
|
|
15
15
|
throw new InvalidArgumentError("Expected a non-negative integer.");
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
const n = Number(value);
|
|
18
|
+
// Reject values that lose precision: above Number.MAX_SAFE_INTEGER the parsed
|
|
19
|
+
// number no longer round-trips to the digits the user typed, so accepting it
|
|
20
|
+
// would silently honour something other than what was asked for.
|
|
21
|
+
if (!Number.isSafeInteger(n)) {
|
|
22
|
+
throw new InvalidArgumentError(`Expected a non-negative integer no greater than ${Number.MAX_SAFE_INTEGER}.`);
|
|
23
|
+
}
|
|
24
|
+
return n;
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* commander value-parser: a non-negative integer with an inclusive upper bound.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iDAAiD;AAGjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,oBAAoB,CAAC,kCAAkC,CAAC,CAAC;IACrE,CAAC;IACD,
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,7 +42,16 @@ export declare class RequestEngine {
|
|
|
42
42
|
private readonly maxResponseBytes;
|
|
43
43
|
private readonly sleep;
|
|
44
44
|
constructor(options?: EngineOptions);
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Build a fully-qualified URL from a path and optional query parameters.
|
|
47
|
+
*
|
|
48
|
+
* The base URL is validated and decomposed via the WHATWG URL parser rather
|
|
49
|
+
* than blindly concatenated, so a scheme-only base (`https:`) or one carrying
|
|
50
|
+
* a query string (`https://host/?x=1`) is rejected with a clear,
|
|
51
|
+
* base-url-specific error instead of silently producing a malformed URL — e.g.
|
|
52
|
+
* promoting an internal path segment to the hostname, or emitting a double-`?`.
|
|
53
|
+
* The base's own path prefix is preserved.
|
|
54
|
+
*/
|
|
46
55
|
buildUrl(path: string, query?: QueryParams): string;
|
|
47
56
|
/** Perform a request with Accept negotiation and transient-error retries. */
|
|
48
57
|
request(method: string, path: string, options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAGhE,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAWD,2EAA2E;AAC3E,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAGhE,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAG5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAWD,2EAA2E;AAC3E,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAiDD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;gBAE1C,OAAO,GAAE,aAAkB;IAgBvC;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM;IA0BnD,6EAA6E;IACvE,OAAO,CACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAmC,GAChF,OAAO,CAAC,WAAW,CAAC;IA+DvB,0DAA0D;IACpD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAwB/D,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -25,6 +25,20 @@ export function stripCrossOriginCredentials(headers, fromUrl, toUrl) {
|
|
|
25
25
|
return safe;
|
|
26
26
|
}
|
|
27
27
|
const realSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
+
/** The media type without parameters or surrounding whitespace. */
|
|
29
|
+
function mediaType(contentType) {
|
|
30
|
+
const semi = contentType.indexOf(";");
|
|
31
|
+
return (semi === -1 ? contentType : contentType.slice(0, semi)).trim();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether a Content-Type denotes JSON: the canonical `application/json`,
|
|
35
|
+
* structured-suffix types (`application/vnd.foo+json`), and the lenient
|
|
36
|
+
* `text/json`. Parameters (`; charset=...`) and case are ignored.
|
|
37
|
+
*/
|
|
38
|
+
function isJsonContentType(contentType) {
|
|
39
|
+
const type = mediaType(contentType).toLowerCase();
|
|
40
|
+
return type === "application/json" || type === "text/json" || type.endsWith("+json");
|
|
41
|
+
}
|
|
28
42
|
/**
|
|
29
43
|
* Normalise a caller-supplied User-Agent into a safe header value.
|
|
30
44
|
*
|
|
@@ -42,10 +56,12 @@ function normalizeUserAgent(value) {
|
|
|
42
56
|
return DEFAULT_USER_AGENT;
|
|
43
57
|
for (let i = 0; i < trimmed.length; i += 1) {
|
|
44
58
|
const code = trimmed.charCodeAt(i);
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
// HTTP header values are limited to (printable) Latin-1. Reject C0 controls,
|
|
60
|
+
// DEL, and anything beyond U+00FF (emoji, CJK, even U+0100) here, before
|
|
61
|
+
// node:http throws an opaque TypeError ("Invalid character in header
|
|
62
|
+
// content") that would otherwise escape as an ungraceful "Unexpected error".
|
|
63
|
+
if (code < 0x20 || code === 0x7f || code > 0xff) {
|
|
64
|
+
throw new HaushaltError("Invalid User-Agent: only printable Latin-1 characters are allowed.");
|
|
49
65
|
}
|
|
50
66
|
}
|
|
51
67
|
return trimmed;
|
|
@@ -75,17 +91,46 @@ export class RequestEngine {
|
|
|
75
91
|
this.maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
|
|
76
92
|
this.sleep = options.sleep ?? realSleep;
|
|
77
93
|
}
|
|
78
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* Build a fully-qualified URL from a path and optional query parameters.
|
|
96
|
+
*
|
|
97
|
+
* The base URL is validated and decomposed via the WHATWG URL parser rather
|
|
98
|
+
* than blindly concatenated, so a scheme-only base (`https:`) or one carrying
|
|
99
|
+
* a query string (`https://host/?x=1`) is rejected with a clear,
|
|
100
|
+
* base-url-specific error instead of silently producing a malformed URL — e.g.
|
|
101
|
+
* promoting an internal path segment to the hostname, or emitting a double-`?`.
|
|
102
|
+
* The base's own path prefix is preserved.
|
|
103
|
+
*/
|
|
79
104
|
buildUrl(path, query) {
|
|
105
|
+
let base;
|
|
106
|
+
try {
|
|
107
|
+
base = new URL(this.baseUrl);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
throw new HaushaltNetworkError(`Invalid base URL: "${this.baseUrl}"`);
|
|
111
|
+
}
|
|
112
|
+
if (base.protocol !== "http:" && base.protocol !== "https:") {
|
|
113
|
+
throw new HaushaltNetworkError(`Unsupported protocol "${base.protocol}" in base URL: "${this.baseUrl}"`);
|
|
114
|
+
}
|
|
115
|
+
if (!base.host) {
|
|
116
|
+
throw new HaushaltNetworkError(`Base URL "${this.baseUrl}" has no host`);
|
|
117
|
+
}
|
|
118
|
+
if (base.search || base.hash) {
|
|
119
|
+
throw new HaushaltNetworkError(`Base URL "${this.baseUrl}" must not contain a query string or fragment`);
|
|
120
|
+
}
|
|
121
|
+
const basePath = base.pathname.replace(/\/+$/, "");
|
|
80
122
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
81
123
|
const qs = query ? buildQueryString(query) : "";
|
|
82
|
-
return `${
|
|
124
|
+
return `${base.origin}${basePath}${normalizedPath}${qs ? `?${qs}` : ""}`;
|
|
83
125
|
}
|
|
84
126
|
/** Perform a request with Accept negotiation and transient-error retries. */
|
|
85
127
|
async request(method, path, options = { accept: "application/json" }) {
|
|
86
128
|
let url = this.buildUrl(path, options.query);
|
|
87
129
|
let headers = {
|
|
88
130
|
Accept: options.accept,
|
|
131
|
+
// Advertise the encodings the transport can decode so an RFC-compliant
|
|
132
|
+
// origin (or a compressing proxy) actually compresses and we still decode it.
|
|
133
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
89
134
|
"User-Agent": this.userAgent,
|
|
90
135
|
};
|
|
91
136
|
let attempt = 0;
|
|
@@ -107,7 +152,10 @@ export class RequestEngine {
|
|
|
107
152
|
continue;
|
|
108
153
|
}
|
|
109
154
|
// Follow redirects, resolving the Location relative to the current URL.
|
|
110
|
-
if (status >= 300 && status < 400 &&
|
|
155
|
+
if (status >= 300 && status < 400 && response.headers["location"]) {
|
|
156
|
+
if (redirects >= this.maxRedirects) {
|
|
157
|
+
throw new HaushaltNetworkError(`Too many redirects (exceeded maxRedirects=${this.maxRedirects}) for ${method} ${url}`);
|
|
158
|
+
}
|
|
111
159
|
const location = response.headers["location"];
|
|
112
160
|
if (typeof location === "string" && location.length > 0) {
|
|
113
161
|
const nextUrl = new URL(location, url);
|
|
@@ -132,7 +180,19 @@ export class RequestEngine {
|
|
|
132
180
|
/** Perform a GET expecting JSON and parse it into `T`. */
|
|
133
181
|
async getJson(path, query) {
|
|
134
182
|
const res = await this.request("GET", path, { query, accept: "application/json" });
|
|
183
|
+
// Honour the Content-Type: a 200 with a clearly non-JSON type (e.g. a
|
|
184
|
+
// captive-portal HTML error page) should report what was actually returned
|
|
185
|
+
// rather than feeding HTML into JSON.parse and blaming a parse failure. A
|
|
186
|
+
// missing/empty Content-Type is treated leniently and still parsed.
|
|
187
|
+
if (res.contentType && !isJsonContentType(res.contentType)) {
|
|
188
|
+
throw new HaushaltParseError(`Expected a JSON response from ${path} but got Content-Type "${mediaType(res.contentType)}"`);
|
|
189
|
+
}
|
|
135
190
|
const text = res.data.toString("utf8");
|
|
191
|
+
// An empty 2xx body (e.g. a 204 No Content) is not valid JSON; report it as
|
|
192
|
+
// such rather than emitting the opaque "Failed to parse JSON" for `""`.
|
|
193
|
+
if (text.trim() === "") {
|
|
194
|
+
throw new HaushaltParseError(`Empty response body from ${path} (expected JSON)`);
|
|
195
|
+
}
|
|
136
196
|
try {
|
|
137
197
|
return JSON.parse(text);
|
|
138
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AACzE,qCAAqC;AAErC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExG,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAgChD,MAAM,0BAA0B,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE5E,2EAA2E;AAC3E,MAAM,UAAU,2BAA2B,CACzC,OAA+B,EAC/B,OAAe,EACf,KAAa;IAEb,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IACtE,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,EAAU,EAAiB,EAAE,CAC9C,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,KAAyB;IACnD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,kBAAkB,CAAC;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AACzE,qCAAqC;AAErC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExG,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAgChD,MAAM,0BAA0B,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE5E,2EAA2E;AAC3E,MAAM,UAAU,2BAA2B,CACzC,OAA+B,EAC/B,OAAe,EACf,KAAa;IAEb,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IACtE,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,EAAU,EAAiB,EAAE,CAC9C,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD,mEAAmE;AACnE,SAAS,SAAS,CAAC,WAAmB;IACpC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IAClD,OAAO,IAAI,KAAK,kBAAkB,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,KAAyB;IACnD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,kBAAkB,CAAC;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,6EAA6E;QAC7E,yEAAyE;QACzE,qEAAqE;QACrE,6EAA6E;QAC7E,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YAChD,MAAM,IAAI,aAAa,CACrB,oEAAoE,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,aAAa;IACP,OAAO,CAAS;IAChB,SAAS,CAAY;IACrB,SAAS,CAAS;IAClB,SAAS,CAAS;IAClB,UAAU,CAAS;IACnB,YAAY,CAAS;IACrB,YAAY,CAAS;IACrB,gBAAgB,CAAS;IACzB,KAAK,CAAgC;IAEtD,YAAY,UAAyB,EAAE;QACrC,2EAA2E;QAC3E,4EAA4E;QAC5E,+DAA+D;QAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC7E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,iBAAiB,CAAC;QACxD,IAAI,CAAC,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,GAAG,CAAC;QAChD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,0BAA0B,CAAC;QAC/E,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;IAC1C,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAY,EAAE,KAAmB;QACxC,IAAI,IAAS,CAAC;QACd,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,oBAAoB,CAAC,sBAAsB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC5D,MAAM,IAAI,oBAAoB,CAC5B,yBAAyB,IAAI,CAAC,QAAQ,mBAAmB,IAAI,CAAC,OAAO,GAAG,CACzE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,oBAAoB,CAAC,aAAa,IAAI,CAAC,OAAO,eAAe,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,IAAI,oBAAoB,CAC5B,aAAa,IAAI,CAAC,OAAO,+CAA+C,CACzE,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAChE,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,GAAG,cAAc,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC3E,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,OAAO,CACX,MAAc,EACd,IAAY,EACZ,UAAmD,EAAE,MAAM,EAAE,kBAAkB,EAAE;QAEjF,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,OAAO,GAA2B;YACpC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,uEAAuE;YACvE,8EAA8E;YAC9E,iBAAiB,EAAE,mBAAmB;YACtC,YAAY,EAAE,IAAI,CAAC,SAAS;SAC7B,CAAC;QAEF,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,yEAAyE;QACzE,SAAS,CAAC;YACR,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC;gBACpC,MAAM;gBACN,GAAG;gBACH,OAAO;gBACP,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAClF,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC/B,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC;YACnD,IAAI,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC3C,OAAO,IAAI,CAAC,CAAC;gBACb,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,CAAC;gBAC9C,SAAS;YACX,CAAC;YAED,wEAAwE;YACxE,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBAClE,IAAI,SAAS,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACnC,MAAM,IAAI,oBAAoB,CAC5B,6CAA6C,IAAI,CAAC,YAAY,SAAS,MAAM,IAAI,GAAG,EAAE,CACvF,CAAC;gBACJ,CAAC;gBACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC9C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;oBACvC,+DAA+D;oBAC/D,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;wBACvE,MAAM,IAAI,oBAAoB,CAC5B,8CAA8C,OAAO,CAAC,QAAQ,EAAE,EAAE,CACnE,CAAC;oBACJ,CAAC;oBACD,4DAA4D;oBAC5D,OAAO,GAAG,2BAA2B,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACxE,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACzB,SAAS,IAAI,CAAC,CAAC;oBACf,SAAS;gBACX,CAAC;YACH,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;YACnE,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAClC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5D,CAAC;YAED,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,KAAmB;QAChD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACnF,sEAAsE;QACtE,2EAA2E;QAC3E,0EAA0E;QAC1E,oEAAoE;QACpE,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,kBAAkB,CAC1B,iCAAiC,IAAI,0BAA0B,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAC7F,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvC,4EAA4E;QAC5E,wEAAwE;QACxE,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvB,MAAM,IAAI,kBAAkB,CAAC,4BAA4B,IAAI,kBAAkB,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC,sCAAsC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,MAAc,EAAE,GAAW,EAAE,MAAc,EAAE,IAAY;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,MAA0B,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4C,CAAC;YAC3E,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ;gBAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;iBACnE,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;gBAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;QACjD,CAAC;QACD,OAAO,IAAI,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"AAQA,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"AAQA,OAAO,IAAI,MAAM,WAAW,CAAC;AAkE7B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAQxE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SA6G5B,CAAC"}
|
package/dist/src/client/http.js
CHANGED
|
@@ -7,7 +7,71 @@
|
|
|
7
7
|
// `http.createServer` in the test-suite.
|
|
8
8
|
import http from "node:http";
|
|
9
9
|
import https from "node:https";
|
|
10
|
+
import zlib from "node:zlib";
|
|
11
|
+
import { promisify } from "node:util";
|
|
10
12
|
import { HaushaltNetworkError } from "./errors.js";
|
|
13
|
+
// Async (libuv thread-pool) variants of the zlib calls, so decoding a large body
|
|
14
|
+
// does not block the event loop — this transport ships as a reusable library.
|
|
15
|
+
const gunzip = promisify(zlib.gunzip);
|
|
16
|
+
const inflate = promisify(zlib.inflate);
|
|
17
|
+
const inflateRaw = promisify(zlib.inflateRaw);
|
|
18
|
+
const brotliDecompress = promisify(zlib.brotliDecompress);
|
|
19
|
+
// `req.setTimeout` holds the delay in a 32-bit signed integer. A larger value
|
|
20
|
+
// makes Node emit a `TimeoutOverflowWarning` to stderr and silently truncate the
|
|
21
|
+
// timer, so clamp here: the effective timeout is already unbounded for practical
|
|
22
|
+
// purposes (~24.8 days).
|
|
23
|
+
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
24
|
+
/**
|
|
25
|
+
* Decompress a body according to its Content-Encoding (identity if none/unknown).
|
|
26
|
+
*
|
|
27
|
+
* `maxBytes` (when > 0) bounds the *decompressed* output via zlib's
|
|
28
|
+
* `maxOutputLength`: a small compressed body can expand to many gigabytes
|
|
29
|
+
* ("decompression bomb"), so capping only the compressed wire bytes is not
|
|
30
|
+
* enough. Past the cap zlib throws `ERR_BUFFER_TOO_LARGE`, which is turned into
|
|
31
|
+
* the same documented size-cap error the wire-size cap produces.
|
|
32
|
+
*/
|
|
33
|
+
async function decode(body, encoding, maxBytes) {
|
|
34
|
+
const limit = maxBytes && maxBytes > 0 ? { maxOutputLength: maxBytes } : {};
|
|
35
|
+
const overCap = () => new HaushaltNetworkError(`Response exceeded maxResponseBytes (${maxBytes})`);
|
|
36
|
+
const isOverCap = (err) => typeof err === "object" &&
|
|
37
|
+
err !== null &&
|
|
38
|
+
err.code === "ERR_BUFFER_TOO_LARGE";
|
|
39
|
+
try {
|
|
40
|
+
switch ((encoding ?? "").toLowerCase()) {
|
|
41
|
+
case "gzip":
|
|
42
|
+
case "x-gzip":
|
|
43
|
+
return await gunzip(body, limit);
|
|
44
|
+
case "deflate":
|
|
45
|
+
// `deflate` is ambiguous: some servers send zlib-wrapped data (RFC 1950),
|
|
46
|
+
// some send raw DEFLATE (RFC 1951). Try zlib-wrapped first, then raw.
|
|
47
|
+
try {
|
|
48
|
+
return await inflate(body, limit);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (isOverCap(err))
|
|
52
|
+
throw err; // a size-cap hit, not a wrapper mismatch
|
|
53
|
+
return await inflateRaw(body, limit);
|
|
54
|
+
}
|
|
55
|
+
case "br":
|
|
56
|
+
return await brotliDecompress(body, limit);
|
|
57
|
+
default:
|
|
58
|
+
if (maxBytes && maxBytes > 0 && body.length > maxBytes)
|
|
59
|
+
throw overCap();
|
|
60
|
+
return body;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (isOverCap(err))
|
|
65
|
+
throw overCap();
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Wrap a thrown value as a HaushaltNetworkError unless it already is one. */
|
|
70
|
+
function toNetworkError(err) {
|
|
71
|
+
if (err instanceof HaushaltNetworkError)
|
|
72
|
+
return err;
|
|
73
|
+
return new HaushaltNetworkError(err instanceof Error ? err.message : String(err), { cause: err });
|
|
74
|
+
}
|
|
11
75
|
/**
|
|
12
76
|
* Default transport. Resolves with the raw response (including non-2xx) — status
|
|
13
77
|
* interpretation is the client's job. Rejects only on transport-level failures
|
|
@@ -32,10 +96,7 @@ export const nodeHttpTransport = (request) => new Promise((resolve, reject) => {
|
|
|
32
96
|
const isHttps = url.protocol === "https:";
|
|
33
97
|
const driver = isHttps ? https : http;
|
|
34
98
|
const maxBytes = request.maxResponseBytes;
|
|
35
|
-
const
|
|
36
|
-
method: request.method,
|
|
37
|
-
headers: request.headers,
|
|
38
|
-
}, (res) => {
|
|
99
|
+
const onResponse = (res) => {
|
|
39
100
|
const chunks = [];
|
|
40
101
|
let received = 0;
|
|
41
102
|
let aborted = false;
|
|
@@ -54,10 +115,19 @@ export const nodeHttpTransport = (request) => new Promise((resolve, reject) => {
|
|
|
54
115
|
res.on("end", () => {
|
|
55
116
|
if (aborted)
|
|
56
117
|
return;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
118
|
+
const raw = Buffer.concat(chunks);
|
|
119
|
+
decode(raw, res.headers["content-encoding"], maxBytes).then((body) => {
|
|
120
|
+
// The body is now decoded; drop the encoding header so downstream
|
|
121
|
+
// consumers don't try to decode it a second time.
|
|
122
|
+
const headers = { ...res.headers };
|
|
123
|
+
delete headers["content-encoding"];
|
|
124
|
+
resolve({ status: res.statusCode ?? 0, headers, body });
|
|
125
|
+
}, (err) => {
|
|
126
|
+
if (err instanceof HaushaltNetworkError) {
|
|
127
|
+
reject(err);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
reject(new HaushaltNetworkError(`Failed to decode ${res.headers["content-encoding"]} response body`, { cause: err }));
|
|
61
131
|
});
|
|
62
132
|
});
|
|
63
133
|
res.on("error", (err) => {
|
|
@@ -65,10 +135,24 @@ export const nodeHttpTransport = (request) => new Promise((resolve, reject) => {
|
|
|
65
135
|
return; // we already rejected with the size-cap error
|
|
66
136
|
reject(new HaushaltNetworkError(`Response stream error: ${err.message}`, { cause: err }));
|
|
67
137
|
});
|
|
68
|
-
}
|
|
138
|
+
};
|
|
139
|
+
let req;
|
|
140
|
+
try {
|
|
141
|
+
// Node validates the outgoing headers synchronously here. An un-sendable
|
|
142
|
+
// value (e.g. a non-Latin-1 --user-agent) makes it throw a TypeError
|
|
143
|
+
// *before* the request is sent; surface it as the typed transport error
|
|
144
|
+
// rather than letting a bare TypeError escape to the CLI's "Unexpected
|
|
145
|
+
// error" fallback.
|
|
146
|
+
req = driver.request(url, { method: request.method, headers: request.headers }, onResponse);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
reject(toNetworkError(err));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
69
152
|
if (request.timeoutMs && request.timeoutMs > 0) {
|
|
70
|
-
|
|
71
|
-
|
|
153
|
+
const timeoutMs = Math.min(request.timeoutMs, MAX_TIMEOUT_MS);
|
|
154
|
+
req.setTimeout(timeoutMs, () => {
|
|
155
|
+
req.destroy(new HaushaltNetworkError(`Request timed out after ${timeoutMs}ms`));
|
|
72
156
|
});
|
|
73
157
|
}
|
|
74
158
|
req.on("error", (err) => {
|
|
@@ -82,8 +166,13 @@ export const nodeHttpTransport = (request) => new Promise((resolve, reject) => {
|
|
|
82
166
|
cause: err,
|
|
83
167
|
}));
|
|
84
168
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
169
|
+
try {
|
|
170
|
+
if (request.body !== undefined)
|
|
171
|
+
req.write(request.body);
|
|
172
|
+
req.end();
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
reject(toNetworkError(err));
|
|
176
|
+
}
|
|
88
177
|
});
|
|
89
178
|
//# sourceMappingURL=http.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,iDAAiD;AACjD,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,8EAA8E;AAC9E,yCAAyC;AAEzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"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"}
|