@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 CHANGED
@@ -1,192 +1,199 @@
1
1
  # bundeshaushalt-cli
2
2
 
3
- A TypeScript **API client** and **command-line interface** for the open
4
- [Bundeshaushalt](https://bundeshaushalt.de/) budget-data API (`bundeshaushalt.de`)
5
- — the **German federal budget**: expenses and income by budget item, functional
6
- area or economic group, planned vs. realised.
7
-
8
- - **Zero runtime HTTP dependencies** — built on Node's built-in `http`/`https` (no axios, no fetch polyfill).
9
- - **One small dependency** for the CLI: [`commander`](https://github.com/tj/commander.js).
10
- - **Strongly typed** typed budget elements, metadata and the account/quota/unit enums.
11
- - **Well tested** unit tests on Node's built-in test runner (`node --test`), every HTTP response mocked.
12
- - **Read-only, no auth** the budget-data API needs no key; this client only reads.
13
-
14
- ## Requirements
15
-
16
- - Node.js **>= 20** (uses the stable built-in test runner, ESM and top-level `await`).
3
+ [![CI](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/ci.yml)
4
+ [![Release](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/release.yml/badge.svg)](https://github.com/maschinenlesbar-org/bundeshaushalt-cli/actions/workflows/release.yml)
5
+ [![npm](https://img.shields.io/npm/v/@maschinenlesbar.org/bundeshaushalt-cli)](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 install
22
- npm run build # compiles TypeScript to dist/
30
+ npm i -g @maschinenlesbar.org/bundeshaushalt-cli
23
31
  ```
24
32
 
25
- Run the CLI without a global install:
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
- A query is a **year** + **account** (`expenses` / `income`). Optionally narrow by:
43
+ No setup needed the endpoint requires no key. Your first query:
38
44
 
39
- - **quota** — `target` (planned) or `actual` (realised),
40
- - **unit** — `single` (budget item), `function` (functional area) or `group` (economic group),
41
- - **id** — drill into one element (a budget number; `G-` prefix for groups, `F-` for functions).
45
+ ```bash
46
+ bundeshaushalt expenses 2024
47
+ ```
42
48
 
43
- The response carries the selected `detail`, its `children` (so you can walk the
44
- tree by passing a child's `id` back in), `parents`, and `related` cross-references.
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
- > **Stability / data coverage.** This client talks to an **undocumented, internal
47
- > endpoint** of the portal (`/internalapi/budgetData` note the `internalapi`
48
- > path). It is **not** a published, stable public API: it can change shape,
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
- ### Global options
56
+ Drill into one budget item by taking an `id` from those results:
55
57
 
56
- | Option | Description |
57
- | --- | --- |
58
- | `--base-url <url>` | API base URL (default `https://bundeshaushalt.de`) |
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
- ### Commands
62
+ ## Commands
70
63
 
71
64
  ```text
72
- budget <year> <account> [--quota target|actual] [--unit single|function|group] [--id <id>]
73
- expenses <year> [--quota] [--unit] [--id] shortcut for: budget <year> expenses
74
- income <year> [--quota] [--unit] [--id] shortcut for: budget <year> 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
- (`<year>` is a four-digit year between `2012` and the current year, inclusive;
78
- the upper bound is derived from the current year so it stays meaningful over time.)
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
- ### Examples
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 income, 2023
87
- bundeshaushalt income 2023 --quota actual
92
+ # Realised (actual) expenses — compare with planned (target, the default)
93
+ bundeshaushalt expenses 2023 --quota actual
88
94
 
89
- # Expenses grouped by economic group
95
+ # Break expenses down by economic group (Gruppe)
90
96
  bundeshaushalt budget 2024 expenses --unit group
91
97
 
92
- # Drill into one budget element by id
93
- bundeshaushalt budget 2024 expenses --id 090168301
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
- ## Library usage
104
+ # Drill into an economic group (G- prefix)
105
+ bundeshaushalt budget 2024 expenses --unit group --id G-5
101
106
 
102
- ```ts
103
- import { BundeshaushaltClient, HaushaltApiError } from "@maschinenlesbar.org/bundeshaushalt-cli";
107
+ # Look at a historical year
108
+ bundeshaushalt expenses 2015 --quota actual
109
+ ```
104
110
 
105
- const client = new BundeshaushaltClient(); // defaults to https://bundeshaushalt.de
111
+ ## Output & scripting
106
112
 
107
- const top = await client.budgetData({ year: 2024, account: "expenses" });
108
- console.log(top.meta.year, top.children.length, "children");
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
- const drill = await client.budgetData({ year: 2024, account: "expenses", id: "090168301" });
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
- try {
113
- await client.budgetData({ year: 1999, account: "expenses" });
114
- } catch (err) {
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
- ### Client options
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
- ### Methods
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
- src/
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
- **Design notes**
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
- - The HTTP layer is a single `Transport` function (`(req) => Promise<HttpResponse>`). The default
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
- ## Testing
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
- ```bash
173
- npm test # builds, then runs `node --test` over dist/test
174
- ```
180
+ ## Learn more
175
181
 
176
- - **`query.test.ts`**query-string serialisation.
177
- - **`http.test.ts`**the default transport against a real loopback `http.createServer`.
178
- - **`engine.test.ts`**URL building, JSON decoding, error mapping, 429/503 retry, redirects — mocked transport.
179
- - **`client.test.ts`**the budget-data URL/param mapping and optional-parameter pruning mocked transport.
180
- - **`cli.test.ts`** — command parsing, the expenses/income shortcuts, validation and exit codes — mocked client.
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
- ## Continuous integration
188
+ ## Data license
183
189
 
184
- GitHub Actions workflows under `.github/workflows/`:
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
- - **ci.yml** — type-check, build and test on Node 20/22/24 for every push and PR.
187
- - **release.yml** on a `v*` tag: verify the tag matches `package.json`, test, `npm pack`, and create a GitHub Release with the tarball.
188
- - **publish.yml** manual dispatch: publish to npm via OIDC **Trusted Publishing** (no stored `NPM_TOKEN`) with provenance.
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;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAgFxC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAiC5E"}
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
- if (opts["quota"] !== undefined) {
33
- params.quota = assertEnum(String(opts["quota"]), QuotaValues, "quota");
34
- }
35
- if (opts["unit"] !== undefined) {
36
- params.unit = assertEnum(String(opts["unit"]), UnitValues, "unit");
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
- .option("--quota <quota>", `target | actual (default target)`)
64
- .option("--unit <unit>", `single | function | group (default single)`)
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":"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"}
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,CA2BjE"}
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"}
@@ -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; default 100 MiB)", parseIntArg)
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;SACrF,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,kEAAkE,EAClE,WAAW,CACZ;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
+ {"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,CAKjD;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"}
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"}
@@ -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
- return Number(value);
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,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,OAAO,CAAC,KAAa,EAAU,EAAE;QAC/B,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,MAAM,IAAI,oBAAoB,CAAC,sCAAsC,GAAG,GAAG,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,OAAqB,EACrB,OAAe;IAEf,IAAI,CAAE,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,aAAa,CAAC,WAAW,OAAO,KAAK,KAAK,uBAAuB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,KAAU,CAAC;AACpB,CAAC;AAWD,uEAAuE;AACvE,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IACnE,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC;IACrE,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACzE,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC5E,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS;QAAE,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAC9F,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,IAAa,EAAE,MAAqB,EAAE,KAAc;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC;AASD;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CACpB,IAAa,EACb,EAAgE;IAEhE,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAY,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAa,CAAC;QAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,EAAmB,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC"}
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
- /** Build a fully-qualified URL from a path and optional query parameters. */
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;AA6BD,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,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM;IAMnD,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;IAuDvB,0DAA0D;IACpD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAU/D,OAAO,CAAC,UAAU;CAYnB"}
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
- // Reject C0 controls (incl. CR/LF/NUL) and DEL before they reach node:http,
46
- // which would otherwise throw an opaque TypeError ("Invalid character...").
47
- if (code < 0x20 || code === 0x7f) {
48
- throw new HaushaltError("Invalid User-Agent: control characters are not allowed.");
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
- /** Build a fully-qualified URL from a path and optional query parameters. */
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 `${this.baseUrl}${normalizedPath}${qs ? `?${qs}` : ""}`;
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 && redirects < this.maxRedirects) {
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":"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"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/engine.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"AAQA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,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;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAiF5B,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"}
@@ -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 req = driver.request(url, {
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
- resolve({
58
- status: res.statusCode ?? 0,
59
- headers: res.headers,
60
- body: Buffer.concat(chunks),
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
- req.setTimeout(request.timeoutMs, () => {
71
- req.destroy(new HaushaltNetworkError(`Request timed out after ${request.timeoutMs}ms`));
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
- if (request.body !== undefined)
86
- req.write(request.body);
87
- req.end();
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":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/client/http.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maschinenlesbar.org/bundeshaushalt-cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "TypeScript API client and CLI for the open German federal budget API (bundeshaushalt.de)",
5
5
  "type": "module",
6
6
  "bin": {