@maschinenlesbar.org/pegel-online-cli 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +26 -14
  2. package/dist/src/cli/commands/stations.d.ts.map +1 -1
  3. package/dist/src/cli/commands/stations.js +6 -5
  4. package/dist/src/cli/commands/stations.js.map +1 -1
  5. package/dist/src/cli/commands/timeseries.d.ts.map +1 -1
  6. package/dist/src/cli/commands/timeseries.js +10 -11
  7. package/dist/src/cli/commands/timeseries.js.map +1 -1
  8. package/dist/src/cli/index.js +2 -0
  9. package/dist/src/cli/index.js.map +1 -1
  10. package/dist/src/cli/io.d.ts +17 -0
  11. package/dist/src/cli/io.d.ts.map +1 -1
  12. package/dist/src/cli/io.js +22 -0
  13. package/dist/src/cli/io.js.map +1 -1
  14. package/dist/src/cli/program.d.ts.map +1 -1
  15. package/dist/src/cli/program.js +4 -3
  16. package/dist/src/cli/program.js.map +1 -1
  17. package/dist/src/cli/shared.d.ts +19 -6
  18. package/dist/src/cli/shared.d.ts.map +1 -1
  19. package/dist/src/cli/shared.js +66 -15
  20. package/dist/src/cli/shared.js.map +1 -1
  21. package/dist/src/client/client.d.ts.map +1 -1
  22. package/dist/src/client/client.js +51 -15
  23. package/dist/src/client/client.js.map +1 -1
  24. package/dist/src/client/engine.d.ts +51 -5
  25. package/dist/src/client/engine.d.ts.map +1 -1
  26. package/dist/src/client/engine.js +157 -39
  27. package/dist/src/client/engine.js.map +1 -1
  28. package/dist/src/client/errors.d.ts +15 -0
  29. package/dist/src/client/errors.d.ts.map +1 -1
  30. package/dist/src/client/errors.js +42 -3
  31. package/dist/src/client/errors.js.map +1 -1
  32. package/dist/src/client/http.js +3 -3
  33. package/dist/src/client/http.js.map +1 -1
  34. package/dist/src/client/index.d.ts +2 -2
  35. package/dist/src/client/index.d.ts.map +1 -1
  36. package/dist/src/client/index.js +2 -2
  37. package/dist/src/client/index.js.map +1 -1
  38. package/dist/src/client/types.d.ts +29 -2
  39. package/dist/src/client/types.d.ts.map +1 -1
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -86,16 +86,20 @@ level); other codes include `Q` (flow/discharge), `WT` (water temperature), and
86
86
  | `--waters <shortname>` | filter by water shortname (see `waters`) |
87
87
  | `--fuzzy-id <id>` | fuzzy match against short/long name |
88
88
  | `--include-timeseries` | embed each station's timeseries list |
89
- | `--include-current` | embed the current measurement |
90
- | `--include-characteristic` | embed characteristic (gauge-mark) values |
89
+ | `--include-current` | embed the current measurement in each timeseries (implies `--include-timeseries`) |
90
+ | `--include-characteristic` | embed characteristic (gauge-mark) values in each timeseries (implies `--include-timeseries`) |
91
91
 
92
92
  ### `stations get` options
93
93
 
94
94
  | Flag | Meaning |
95
95
  | --- | --- |
96
96
  | `--include-timeseries` | embed the station's timeseries list |
97
- | `--include-current` | embed the current measurement |
98
- | `--include-characteristic` | embed characteristic (gauge-mark) values |
97
+ | `--include-current` | embed the current measurement in each timeseries (implies `--include-timeseries`) |
98
+ | `--include-characteristic` | embed characteristic (gauge-mark) values in each timeseries (implies `--include-timeseries`) |
99
+
100
+ The API nests the current measurement and the gauge marks *inside* each
101
+ timeseries and drops them without the timeseries list, so `--include-current` and
102
+ `--include-characteristic` turn on `--include-timeseries` themselves.
99
103
 
100
104
  ### `measurements` options
101
105
 
@@ -187,15 +191,23 @@ both `pegel --compact waters` and `pegel waters --compact` do the same thing.
187
191
  `PATH`. Run `npm bin -g` to find it and add it, or run via
188
192
  `npx @maschinenlesbar.org/pegel-online-cli …`.
189
193
  - **Exit `2` / "invalid argument"** — check the command syntax: a `<station>`
190
- argument is required, and `--start` / `--end` must be valid ISO-8601 instants or
191
- periods (e.g. `P7D`). Run `pegel <command> --help` for the exact signature.
192
- - **Exit `4` / "not found"** — the station shortname or id doesn't exist. Run
193
- `pegel stations list --fuzzy-id <name>` or `pegel waters` to find the right
194
- shortname.
194
+ argument is required, and no argument or option value may be blank (or `.` /
195
+ `..` for an id). Run `pegel <command> --help` for the exact signature.
196
+ - **Exit `4` / "not found"** — the station shortname or id doesn't exist, or the
197
+ station doesn't publish the requested series (`Timeseries does not exist.` /
198
+ `Current measurement does not exist.`). Run `pegel stations list --fuzzy-id <name>`
199
+ or `pegel waters` to find the right shortname, and
200
+ `pegel stations get <station> --include-timeseries | jq -r '.timeseries[].shortname'`
201
+ to see which series codes it exposes.
202
+ - **Exit `1` / `HTTP 400` on `measurements`** — `--start` / `--end` are not checked
203
+ locally; the API rejects a value that is not an ISO-8601 instant or period
204
+ (`Given start parameter is neither a valid ISO date time, nor an ISO period.`) and
205
+ a window whose start is not before its end (e.g. a start in the future). Use
206
+ `P7D`, not `7d`.
207
+ - **Empty `[]` from `measurements`** — the window lies outside the data the API
208
+ keeps (about the last month), e.g. a date from earlier in the year.
195
209
  - **Exit `1` / network error** — connectivity, DNS, or a timeout. Try again, or
196
210
  raise the limit with `--timeout 60000`.
197
- - **Empty `timeseries` array** — the station doesn't publish the requested series.
198
- Run `pegel timeseries <station>` to see which codes it actually exposes.
199
211
 
200
212
  ## Global options
201
213
 
@@ -206,10 +218,10 @@ These apply to every command and may be given before *or* after it:
206
218
  | `-V, --version` | Print the version number |
207
219
  | `-h, --help` | Show help for the program or a command |
208
220
  | `--compact` | Print JSON on a single line instead of pretty-printed |
209
- | `--base-url <url>` | API base URL (default `https://www.pegelonline.wsv.de`) |
221
+ | `--base-url <url>` | API base URL (default `https://www.pegelonline.wsv.de`); http(s) only, a path prefix is fine, no query (`?`), fragment (`#`) or surrounding whitespace; userinfo is sent as Basic auth but shown as `***` in messages |
210
222
  | `--timeout <ms>` | Time limit per request in milliseconds, reading the whole response included (default `30000`; at most `2147483647`) |
211
- | `--user-agent <ua>` | `User-Agent` header value |
212
- | `--max-retries <n>` | Retries for transient `429`/`503` responses (default `2`) |
223
+ | `--user-agent <ua>` | `User-Agent` header value (not blank; Latin-1, no control characters) |
224
+ | `--max-retries <n>` | Retries for transient `429`/`503` responses, `0`–`10` (default `2`); each waits the server's `Retry-After` (up to 30 s; a longer one is not retried), else 200 ms × attempt |
213
225
  | `--max-response-bytes <n>` | Cap response body size in bytes (`0` = unlimited; default 100 MiB) |
214
226
 
215
227
  ## Learn more
@@ -1 +1 @@
1
- {"version":3,"file":"stations.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/stations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAyBxC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAiC7E"}
1
+ {"version":3,"file":"stations.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/stations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAmCxC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAkC7E"}
@@ -1,5 +1,5 @@
1
1
  import { Option } from "commander";
2
- import { action, parseNonEmpty, renderJson, requireArg } from "../shared.js";
2
+ import { STATION_HELP, action, parseNonEmpty, parsePathArg, renderJson } from "../shared.js";
3
3
  /** commander accumulator for a repeatable string option. */
4
4
  function collect(value, previous = []) {
5
5
  return previous.concat([parseNonEmpty(value)]);
@@ -15,8 +15,8 @@ function includesFrom(opts) {
15
15
  function addIncludeOptions(cmd) {
16
16
  return cmd
17
17
  .addOption(new Option("--include-timeseries", "embed each station's timeseries list"))
18
- .addOption(new Option("--include-current", "embed the current measurement"))
19
- .addOption(new Option("--include-characteristic", "embed characteristic (gauge-mark) values"));
18
+ .addOption(new Option("--include-current", "embed the current measurement in each timeseries (implies --include-timeseries)"))
19
+ .addOption(new Option("--include-characteristic", "embed characteristic (gauge-mark) values in each timeseries (implies --include-timeseries)"));
20
20
  }
21
21
  export function registerStationCommands(program, deps) {
22
22
  const stations = program.command("stations").description("Measuring stations");
@@ -36,10 +36,11 @@ export function registerStationCommands(program, deps) {
36
36
  renderJson(deps, global, await client.stations.list(params));
37
37
  }));
38
38
  const get = stations
39
- .command("get <station>")
39
+ .command("get")
40
+ .argument("<station>", STATION_HELP, parsePathArg)
40
41
  .description("Get one station by uuid/number/shortname/longname");
41
42
  addIncludeOptions(get).action(action(deps, async ({ client, global, opts }, [station]) => {
42
- renderJson(deps, global, await client.stations.get(requireArg("station", station), includesFrom(opts)));
43
+ renderJson(deps, global, await client.stations.get(station, includesFrom(opts)));
43
44
  }));
44
45
  }
45
46
  //# sourceMappingURL=stations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stations.js","sourceRoot":"","sources":["../../../../src/cli/commands/stations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG7E,4DAA4D;AAC5D,SAAS,OAAO,CAAC,KAAa,EAAE,QAAQ,GAAa,EAAE;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,gEAAgE;AAChE,SAAS,YAAY,CAAC,IAA6B;IACjD,OAAO;QACL,iBAAiB,EAAE,IAAI,CAAC,mBAAmB,CAAwB;QACnE,yBAAyB,EAAE,IAAI,CAAC,gBAAgB,CAAwB;QACxE,2BAA2B,EAAE,IAAI,CAAC,uBAAuB,CAAwB;KAClF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAY;IACrC,OAAO,GAAG;SACP,SAAS,CAAC,IAAI,MAAM,CAAC,sBAAsB,EAAE,sCAAsC,CAAC,CAAC;SACrF,SAAS,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,+BAA+B,CAAC,CAAC;SAC3E,SAAS,CAAC,IAAI,MAAM,CAAC,0BAA0B,EAAE,0CAA0C,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAgB,EAAE,IAAa;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAE/E,MAAM,IAAI,GAAG,QAAQ;SAClB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,YAAY,EAAE,yDAAyD,EAAE,OAAO,CAAC;SACxF,MAAM,CAAC,sBAAsB,EAAE,0CAA0C,EAAE,aAAa,CAAC;SACzF,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAC9D,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,CAC5B,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAsB;YAChC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAyB;YACxC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAuB;YAC5C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAuB;YAC9C,GAAG,YAAY,CAAC,IAAI,CAAC;SACtB,CAAC;QACF,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,GAAG,GAAG,QAAQ;SACjB,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,mDAAmD,CAAC,CAAC;IACpE,iBAAiB,CAAC,GAAG,CAAC,CAAC,MAAM,CAC3B,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE;QACzD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAC9E,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"stations.js","sourceRoot":"","sources":["../../../../src/cli/commands/stations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG7F,4DAA4D;AAC5D,SAAS,OAAO,CAAC,KAAa,EAAE,QAAQ,GAAa,EAAE;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,gEAAgE;AAChE,SAAS,YAAY,CAAC,IAA6B;IACjD,OAAO;QACL,iBAAiB,EAAE,IAAI,CAAC,mBAAmB,CAAwB;QACnE,yBAAyB,EAAE,IAAI,CAAC,gBAAgB,CAAwB;QACxE,2BAA2B,EAAE,IAAI,CAAC,uBAAuB,CAAwB;KAClF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAY;IACrC,OAAO,GAAG;SACP,SAAS,CAAC,IAAI,MAAM,CAAC,sBAAsB,EAAE,sCAAsC,CAAC,CAAC;SACrF,SAAS,CACR,IAAI,MAAM,CACR,mBAAmB,EACnB,iFAAiF,CAClF,CACF;SACA,SAAS,CACR,IAAI,MAAM,CACR,0BAA0B,EAC1B,4FAA4F,CAC7F,CACF,CAAC;AACN,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAgB,EAAE,IAAa;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAE/E,MAAM,IAAI,GAAG,QAAQ;SAClB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,YAAY,EAAE,yDAAyD,EAAE,OAAO,CAAC;SACxF,MAAM,CAAC,sBAAsB,EAAE,0CAA0C,EAAE,aAAa,CAAC;SACzF,MAAM,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAC9D,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,CAC5B,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAsB;YAChC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAyB;YACxC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAuB;YAC5C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAuB;YAC9C,GAAG,YAAY,CAAC,IAAI,CAAC;SACtB,CAAC;QACF,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,CAAC,CAAC,CACH,CAAC;IAEF,MAAM,GAAG,GAAG,QAAQ;SACjB,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;SACjD,WAAW,CAAC,mDAAmD,CAAC,CAAC;IACpE,iBAAiB,CAAC,GAAG,CAAC,CAAC,MAAM,CAC3B,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE;QACzD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CACxD,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"timeseries.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/timeseries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAMxC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CA2DhF"}
1
+ {"version":3,"file":"timeseries.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/timeseries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAKxC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CA2DhF"}
@@ -1,32 +1,31 @@
1
- import { action, parseNonEmpty, renderJson, requireArg, timeseriesOr } from "../shared.js";
2
- const STATION_HELP = "station uuid, number, shortname or longname";
1
+ import { STATION_HELP, action, parseNonEmpty, parsePathArg, renderJson, timeseriesOr } from "../shared.js";
3
2
  const TIMESERIES_HELP = "timeseries shortname, e.g. W (water level) or Q (flow)";
4
3
  export function registerTimeseriesCommands(program, deps) {
5
4
  program
6
5
  .command("timeseries")
7
- .argument("<station>", STATION_HELP)
8
- .argument("[timeseries]", TIMESERIES_HELP, parseNonEmpty)
6
+ .argument("<station>", STATION_HELP, parsePathArg)
7
+ .argument("[timeseries]", TIMESERIES_HELP, parsePathArg)
9
8
  .description("Timeseries metadata (timeseries defaults to 'W' = water level)")
10
9
  .action(action(deps, async ({ client, global }, [station, ts]) => {
11
- renderJson(deps, global, await client.timeseries.get(requireArg("station", station), timeseriesOr(ts)));
10
+ renderJson(deps, global, await client.timeseries.get(station, timeseriesOr(ts)));
12
11
  }));
13
12
  program
14
13
  .command("current")
15
- .argument("<station>", STATION_HELP)
16
- .argument("[timeseries]", TIMESERIES_HELP, parseNonEmpty)
14
+ .argument("<station>", STATION_HELP, parsePathArg)
15
+ .argument("[timeseries]", TIMESERIES_HELP, parsePathArg)
17
16
  .description("The current measurement (timeseries defaults to 'W')")
18
17
  .action(action(deps, async ({ client, global }, [station, ts]) => {
19
- renderJson(deps, global, await client.timeseries.currentMeasurement(requireArg("station", station), timeseriesOr(ts)));
18
+ renderJson(deps, global, await client.timeseries.currentMeasurement(station, timeseriesOr(ts)));
20
19
  }));
21
20
  program
22
21
  .command("measurements")
23
- .argument("<station>", STATION_HELP)
24
- .argument("[timeseries]", TIMESERIES_HELP, parseNonEmpty)
22
+ .argument("<station>", STATION_HELP, parsePathArg)
23
+ .argument("[timeseries]", TIMESERIES_HELP, parsePathArg)
25
24
  .description("A window of measurements (timeseries defaults to 'W')")
26
25
  .option("--start <iso>", "window start: ISO-8601 instant, or a period like P7D", parseNonEmpty)
27
26
  .option("--end <iso>", "window end: ISO-8601 instant", parseNonEmpty)
28
27
  .action(action(deps, async ({ client, global, opts }, [station, ts]) => {
29
- renderJson(deps, global, await client.timeseries.measurements(requireArg("station", station), timeseriesOr(ts), {
28
+ renderJson(deps, global, await client.timeseries.measurements(station, timeseriesOr(ts), {
30
29
  start: opts["start"],
31
30
  end: opts["end"],
32
31
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"timeseries.js","sourceRoot":"","sources":["../../../../src/cli/commands/timeseries.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3F,MAAM,YAAY,GAAG,6CAA6C,CAAC;AACnE,MAAM,eAAe,GAAG,wDAAwD,CAAC;AAEjF,MAAM,UAAU,0BAA0B,CAAC,OAAgB,EAAE,IAAa;IACxE,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;SACnC,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,aAAa,CAAC;SACxD,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QACvD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CAC9E,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;SACnC,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,aAAa,CAAC;SACxD,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QACvD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CAC7F,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;SACnC,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,aAAa,CAAC;SACxD,WAAW,CAAC,uDAAuD,CAAC;SACpE,MAAM,CAAC,eAAe,EAAE,sDAAsD,EAAE,aAAa,CAAC;SAC9F,MAAM,CAAC,aAAa,EAAE,8BAA8B,EAAE,aAAa,CAAC;SACpE,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QAC7D,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE;YACrF,KAAK,EAAE,IAAI,CAAC,OAAO,CAAuB;YAC1C,GAAG,EAAE,IAAI,CAAC,KAAK,CAAuB;SACvC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qCAAqC,CAAC;SAClD,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QACxC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"timeseries.js","sourceRoot":"","sources":["../../../../src/cli/commands/timeseries.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3G,MAAM,eAAe,GAAG,wDAAwD,CAAC;AAEjF,MAAM,UAAU,0BAA0B,CAAC,OAAgB,EAAE,IAAa;IACxE,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;SACjD,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,CAAC;SACvD,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QACvD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,OAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CACxD,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;SACjD,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,CAAC;SACvD,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QACvD,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,OAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CACvE,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;SACjD,QAAQ,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,CAAC;SACvD,WAAW,CAAC,uDAAuD,CAAC;SACpE,MAAM,CAAC,eAAe,EAAE,sDAAsD,EAAE,aAAa,CAAC;SAC9F,MAAM,CAAC,aAAa,EAAE,8BAA8B,EAAE,aAAa,CAAC;SACpE,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;QAC7D,UAAU,CACR,IAAI,EACJ,MAAM,EACN,MAAM,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,OAAQ,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE;YAC/D,KAAK,EAAE,IAAI,CAAC,OAAO,CAAuB;YAC1C,GAAG,EAAE,IAAI,CAAC,KAAK,CAAuB;SACvC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qCAAqC,CAAC;SAClD,MAAM,CACL,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QACxC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  // Binary entry point. Thin shim around run(); all logic lives in run.ts/program.ts.
3
+ import { handleOutputErrors } from "./io.js";
3
4
  import { run } from "./run.js";
5
+ handleOutputErrors();
4
6
  const exitCode = await run(process.argv.slice(2));
5
7
  process.exitCode = exitCode;
6
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AACA,oFAAoF;AAEpF,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";AACA,oFAAoF;AAEpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,kBAAkB,EAAE,CAAC;AACrB,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC"}
@@ -9,5 +9,22 @@ export interface CliDeps {
9
9
  /** Build a client from the resolved global options (injectable for tests). */
10
10
  createClient(options: EngineOptions): PegelOnlineClient;
11
11
  }
12
+ /** The two process streams, as far as `handleOutputErrors` needs them. */
13
+ export interface OutputStreams {
14
+ stdout: Pick<NodeJS.WriteStream, "on">;
15
+ stderr: Pick<NodeJS.WriteStream, "on">;
16
+ }
17
+ /**
18
+ * Handle write errors on stdout/stderr, which Node otherwise reports as an
19
+ * unhandled 'error' event: a raw stack trace and exit 1.
20
+ *
21
+ * A reader that stops early — `| head`, `| jq` exiting on the first match, a closed
22
+ * pager — closes the pipe while the CLI is still writing, and the next write fails
23
+ * with EPIPE. That is ordinary use, so the process exits 0 at once, quietly. Any
24
+ * other stdout error prints one `Output error: <message>` line to stderr and exits
25
+ * 1; any other stderr error exits 1 silently (there is nowhere left to report it).
26
+ * The bin shim installs this once, before `run()`.
27
+ */
28
+ export declare function handleOutputErrors(streams?: OutputStreams, exit?: (code: number) => void): void;
12
29
  export declare const defaultIO: CliIO;
13
30
  //# sourceMappingURL=io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../../src/cli/io.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,KAAK,CAAC;IACV,8EAA8E;IAC9E,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAAC;CACzD;AAED,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC"}
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../../src/cli/io.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,KAAK,CAAC;IACV,8EAA8E;IAC9E,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAAC;CACzD;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACvC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,aAAuB,EAChC,IAAI,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAmC,GAC1D,IAAI,CASN;AAED,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC"}
@@ -1,5 +1,27 @@
1
1
  // I/O seam for the CLI. Everything the CLI writes goes through a CliIO object so
2
2
  // tests can capture output instead of hitting the real stdout/stderr.
3
+ /**
4
+ * Handle write errors on stdout/stderr, which Node otherwise reports as an
5
+ * unhandled 'error' event: a raw stack trace and exit 1.
6
+ *
7
+ * A reader that stops early — `| head`, `| jq` exiting on the first match, a closed
8
+ * pager — closes the pipe while the CLI is still writing, and the next write fails
9
+ * with EPIPE. That is ordinary use, so the process exits 0 at once, quietly. Any
10
+ * other stdout error prints one `Output error: <message>` line to stderr and exits
11
+ * 1; any other stderr error exits 1 silently (there is nowhere left to report it).
12
+ * The bin shim installs this once, before `run()`.
13
+ */
14
+ export function handleOutputErrors(streams = process, exit = (code) => process.exit(code)) {
15
+ streams.stdout.on("error", (err) => {
16
+ if (err.code === "EPIPE")
17
+ return exit(0);
18
+ process.stderr.write(`Output error: ${err.message}\n`);
19
+ exit(1);
20
+ });
21
+ streams.stderr.on("error", (err) => {
22
+ exit(err.code === "EPIPE" ? 0 : 1);
23
+ });
24
+ }
3
25
  export const defaultIO = {
4
26
  out: (text) => process.stdout.write(text + "\n"),
5
27
  err: (text) => process.stderr.write(text + "\n"),
@@ -1 +1 @@
1
- {"version":3,"file":"io.js","sourceRoot":"","sources":["../../../src/cli/io.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,sEAAsE;AAgBtE,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAChD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;CACjD,CAAC"}
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["../../../src/cli/io.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,sEAAsE;AAsBtE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAO,GAAkB,OAAO,EAChC,IAAI,GAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;IAE3D,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACxD,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACxD,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAChD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;CACjD,CAAC"}
@@ -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;AAwBvC,eAAO,MAAM,OAAO,QAAgB,CAAC;AAErC,yEAAyE;AACzE,eAAO,MAAM,WAAW,EAAE,OAGzB,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,GAAE,OAAqB,GAAG,OAAO,CA8BjE"}
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;AAyBvC,eAAO,MAAM,OAAO,QAAgB,CAAC;AAErC,yEAAyE;AACzE,eAAO,MAAM,WAAW,EAAE,OAGzB,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,GAAE,OAAqB,GAAG,OAAO,CAkCjE"}
@@ -7,7 +7,8 @@ import { Command } from "commander";
7
7
  import { defaultIO } from "./io.js";
8
8
  import { PegelOnlineClient } from "../client/client.js";
9
9
  import { MAX_TIMEOUT_MS } from "../client/http.js";
10
- import { parseBoundedInt, parseIntArg, parseBaseUrl } from "./shared.js";
10
+ import { MAX_RETRIES } from "../client/engine.js";
11
+ import { parseBoundedInt, parseIntArg, parseBaseUrl, parseHeaderValue } from "./shared.js";
11
12
  import { registerStationCommands } from "./commands/stations.js";
12
13
  import { registerTimeseriesCommands } from "./commands/timeseries.js";
13
14
  /**
@@ -41,8 +42,8 @@ export function buildProgram(deps = defaultDeps) {
41
42
  .version(VERSION)
42
43
  .option("--base-url <url>", "API base URL", parseBaseUrl, "https://www.pegelonline.wsv.de")
43
44
  .option("--timeout <ms>", "time limit per request in milliseconds, whole response included", parseBoundedInt(0, MAX_TIMEOUT_MS))
44
- .option("--user-agent <ua>", "User-Agent header value")
45
- .option("--max-retries <n>", "retries for transient 429/503 responses", parseIntArg)
45
+ .option("--user-agent <ua>", "User-Agent header value", parseHeaderValue)
46
+ .option("--max-retries <n>", "retries for transient 429/503 responses (0..10; each waits the server's Retry-After, up to 30 s)", parseBoundedInt(0, MAX_RETRIES))
46
47
  .option("--max-response-bytes <n>", "cap response body size in bytes (0 = unlimited; default 100 MiB)", parseIntArg)
47
48
  .option("--compact", "print JSON on a single line instead of pretty-printed")
48
49
  .showHelpAfterError();
@@ -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,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;GAKG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,OAAO,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,iBAAiB,CAAC,OAAO,CAAC;CAC1D,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,IAAI,GAAY,WAAW;IACtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CACV,oDAAoD;QAClD,0DAA0D,CAC7D;SACA,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,gCAAgC,CAAC;SAC1F,MAAM,CACL,gBAAgB,EAChB,iEAAiE,EACjE,eAAe,CAAC,CAAC,EAAE,cAAc,CAAC,CACnC;SACA,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CAAC,mBAAmB,EAAE,yCAAyC,EAAE,WAAW,CAAC;SACnF,MAAM,CACL,0BAA0B,EAC1B,kEAAkE,EAClE,WAAW,CACZ;SACA,MAAM,CAAC,WAAW,EAAE,uDAAuD,CAAC;SAC5E,kBAAkB,EAAE,CAAC;IAExB,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACvC,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE1C,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,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;GAKG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,OAAO,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,iBAAiB,CAAC,OAAO,CAAC;CAC1D,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,IAAI,GAAY,WAAW;IACtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CACV,oDAAoD;QAClD,0DAA0D,CAC7D;SACA,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,gCAAgC,CAAC;SAC1F,MAAM,CACL,gBAAgB,EAChB,iEAAiE,EACjE,eAAe,CAAC,CAAC,EAAE,cAAc,CAAC,CACnC;SACA,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,EAAE,gBAAgB,CAAC;SACxE,MAAM,CACL,mBAAmB,EACnB,kGAAkG,EAClG,eAAe,CAAC,CAAC,EAAE,WAAW,CAAC,CAChC;SACA,MAAM,CACL,0BAA0B,EAC1B,kEAAkE,EAClE,WAAW,CACZ;SACA,MAAM,CAAC,WAAW,EAAE,uDAAuD,CAAC;SAC5E,kBAAkB,EAAE,CAAC;IAExB,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACvC,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE1C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import type { CliDeps } from "./io.js";
2
2
  import type { EngineOptions } from "../client/engine.js";
3
+ /** Help text of every `<station>` positional. */
4
+ export declare const STATION_HELP = "station uuid, number, shortname or longname";
3
5
  /** commander value-parser: a non-negative integer. */
4
6
  export declare function parseIntArg(value: string): number;
5
7
  /** Build a commander value-parser for an integer constrained to [min, max]. */
@@ -9,6 +11,23 @@ export declare function parseBoundedInt(min: number, max: number): (value: strin
9
11
  * otherwise be dropped and the command would silently run unfiltered.
10
12
  */
11
13
  export declare function parseNonEmpty(value: string): string;
14
+ /**
15
+ * commander value-parser for a value that ends up in an HTTP header (`--user-agent`).
16
+ * Node's HTTP layer throws an opaque "Invalid character in header content" at request
17
+ * time for a CR/LF (or any other C0 control or DEL) and for any character above
18
+ * U+00FF, which surfaced as "Unexpected error". Reject those here as a usage error,
19
+ * along with a blank value. Tab is allowed, as in HTTP. Checked by char code so the
20
+ * source stays free of control bytes.
21
+ */
22
+ export declare function parseHeaderValue(value: string): string;
23
+ /**
24
+ * commander value-parser for an id that becomes a URL path segment (the
25
+ * `<station>` and `[timeseries]` positionals): not blank (which would build
26
+ * `/stations//W/...`), and not "." / "..", which
27
+ * encodeURIComponent leaves untouched and URL parsing would resolve, sending the
28
+ * request to a different resource. A usage error, before any request.
29
+ */
30
+ export declare function parsePathArg(value: string): string;
12
31
  /**
13
32
  * commander value-parser for `--base-url`: reject anything that is not a parseable
14
33
  * absolute `http:`/`https:` URL at *parse* time, so a bad scheme (`file:`, `ftp:`)
@@ -18,12 +37,6 @@ export declare function parseNonEmpty(value: string): string;
18
37
  * the user-facing rejection earlier and to the correct exit code.
19
38
  */
20
39
  export declare function parseBaseUrl(value: string): string;
21
- /**
22
- * Validate a required positional argument: reject an empty/blank value rather
23
- * than forwarding it into the URL path (which would produce a malformed request
24
- * like `/stations//W/...`). Returns the trimmed value.
25
- */
26
- export declare function requireArg(name: string, value: string | undefined): string;
27
40
  /**
28
41
  * Default an omitted optional `[timeseries]` positional to "W" (water level),
29
42
  * matching the documented default. A blank value never reaches here: the
@@ -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;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAQnF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWlD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAU1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,SAAM,GAAG,MAAM,CAE9E;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;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWvD;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;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,iDAAiD;AACjD,eAAO,MAAM,YAAY,gDAAgD,CAAC;AAE1E,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAQnF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYtD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBlD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,SAAM,GAAG,MAAM,CAE9E;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;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWvD;AAyBD,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"}
@@ -2,6 +2,8 @@
2
2
  // option resolver, and the JSON result renderer.
3
3
  import { InvalidArgumentError } from "commander";
4
4
  import { PegelError } from "../client/errors.js";
5
+ /** Help text of every `<station>` positional. */
6
+ export const STATION_HELP = "station uuid, number, shortname or longname";
5
7
  /** commander value-parser: a non-negative integer. */
6
8
  export function parseIntArg(value) {
7
9
  // Require a plain decimal integer. Reject blank/whitespace ("" and " " coerce
@@ -37,6 +39,41 @@ export function parseNonEmpty(value) {
37
39
  }
38
40
  return value;
39
41
  }
42
+ /**
43
+ * commander value-parser for a value that ends up in an HTTP header (`--user-agent`).
44
+ * Node's HTTP layer throws an opaque "Invalid character in header content" at request
45
+ * time for a CR/LF (or any other C0 control or DEL) and for any character above
46
+ * U+00FF, which surfaced as "Unexpected error". Reject those here as a usage error,
47
+ * along with a blank value. Tab is allowed, as in HTTP. Checked by char code so the
48
+ * source stays free of control bytes.
49
+ */
50
+ export function parseHeaderValue(value) {
51
+ parseNonEmpty(value);
52
+ for (let i = 0; i < value.length; i++) {
53
+ const c = value.charCodeAt(i);
54
+ if ((c < 0x20 && c !== 0x09) || c === 0x7f) {
55
+ throw new InvalidArgumentError("Value contains control characters.");
56
+ }
57
+ if (c > 0xff) {
58
+ throw new InvalidArgumentError("Value contains characters outside Latin-1 (above U+00FF).");
59
+ }
60
+ }
61
+ return value;
62
+ }
63
+ /**
64
+ * commander value-parser for an id that becomes a URL path segment (the
65
+ * `<station>` and `[timeseries]` positionals): not blank (which would build
66
+ * `/stations//W/...`), and not "." / "..", which
67
+ * encodeURIComponent leaves untouched and URL parsing would resolve, sending the
68
+ * request to a different resource. A usage error, before any request.
69
+ */
70
+ export function parsePathArg(value) {
71
+ parseNonEmpty(value);
72
+ if (value === "." || value === "..") {
73
+ throw new InvalidArgumentError('"." and ".." cannot be used as an id.');
74
+ }
75
+ return value;
76
+ }
40
77
  /**
41
78
  * commander value-parser for `--base-url`: reject anything that is not a parseable
42
79
  * absolute `http:`/`https:` URL at *parse* time, so a bad scheme (`file:`, `ftp:`)
@@ -56,21 +93,15 @@ export function parseBaseUrl(value) {
56
93
  if (url.protocol !== "http:" && url.protocol !== "https:") {
57
94
  throw new InvalidArgumentError("Only http and https URLs are supported.");
58
95
  }
59
- return value;
60
- }
61
- /**
62
- * Validate a required positional argument: reject an empty/blank value rather
63
- * than forwarding it into the URL path (which would produce a malformed request
64
- * like `/stations//W/...`). Returns the trimmed value.
65
- */
66
- export function requireArg(name, value) {
67
- if (value === undefined || value.trim() === "") {
68
- throw new PegelError(`Missing required <${name}> argument.`);
96
+ // Paths are appended to the base URL as a string, so a query or fragment would
97
+ // swallow every request path ("http://h/#f" requests "/" for every command).
98
+ if (/[?#]/.test(value)) {
99
+ throw new InvalidArgumentError("A base URL cannot have a query (?) or fragment (#).");
69
100
  }
70
- // Reject "." / ".." which encodeURIComponent leaves untouched and which would
71
- // otherwise inject a relative path segment into the request URL.
72
- if (value === "." || value === "..") {
73
- throw new PegelError(`Invalid <${name}> argument: "${value}".`);
101
+ // new URL() trims surrounding whitespace silently; the raw value is what the
102
+ // engine uses, so reject it rather than guess.
103
+ if (value !== value.trim()) {
104
+ throw new InvalidArgumentError("A base URL cannot have surrounding whitespace.");
74
105
  }
75
106
  return value;
76
107
  }
@@ -116,9 +147,29 @@ export function escapeControlChars(json) {
116
147
  }
117
148
  return from === 0 ? json : result + json.slice(from);
118
149
  }
150
+ /**
151
+ * JSON.stringify, pretty or compact. A deeply nested value (a hostile or broken
152
+ * response) overflows the stack — the pretty form far sooner than the compact one,
153
+ * which is why the message suggests --compact. The RangeError becomes a PegelError so
154
+ * the CLI prints a clear message instead of "Unexpected error: Maximum call stack
155
+ * size exceeded".
156
+ */
157
+ function stringifyJson(value, compact) {
158
+ try {
159
+ return compact ? JSON.stringify(value) : JSON.stringify(value, null, 2);
160
+ }
161
+ catch (err) {
162
+ if (err instanceof RangeError) {
163
+ throw new PegelError(compact
164
+ ? "The response is nested too deeply to print."
165
+ : "The response is nested too deeply to pretty-print; try --compact.", { cause: err });
166
+ }
167
+ throw err;
168
+ }
169
+ }
119
170
  /** Render a JSON value to stdout, pretty by default, compact with --compact. */
120
171
  export function renderJson(deps, global, value) {
121
- const text = escapeControlChars(global.compact ? JSON.stringify(value) : JSON.stringify(value, null, 2));
172
+ const text = escapeControlChars(stringifyJson(value, global.compact === true));
122
173
  deps.io.out(text);
123
174
  }
124
175
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/cli/shared.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,KAAK,EACV,OAAO,EACP,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAsBpB,mFAAmF;AACnF,cAAM,gBAAgB;IACR,OAAO,CAAC,QAAQ,CAAC,CAAC;IAA9B,YAA6B,CAAC,EAAE,aAAa,EAAI;IAEjD,IAAI,CAAC,MAAM,GAAE,iBAAsB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAUvD;IAED,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjE;CACF;AAED,4FAA4F;AAC5F,cAAM,kBAAkB;IACV,OAAO,CAAC,QAAQ,CAAC,CAAC;IAA9B,YAA6B,CAAC,EAAE,aAAa,EAAI;IAEjD,gEAAgE;IAChE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAK1F;IAED,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAIjF;IAED,YAAY,CACV,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,EAChB,MAAM,GAAE,kBAAuB,GAC9B,OAAO,CAAC,WAAW,EAAE,CAAC,CAKxB;CACF;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IAEvC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC,YAAY,OAAO,GAAE,aAAkB,EAItC;IAED,kEAAkE;IAClE,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAEzB;CACF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client/client.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,KAAK,EACV,OAAO,EACP,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AA8DpB,mFAAmF;AACnF,cAAM,gBAAgB;IACR,OAAO,CAAC,QAAQ,CAAC,CAAC;IAA9B,YAA6B,CAAC,EAAE,aAAa,EAAI;IAEjD,IAAI,CAAC,MAAM,GAAE,iBAAsB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAQvD;IAEK,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvE;CACF;AAED,4FAA4F;AAC5F,cAAM,kBAAkB;IACV,OAAO,CAAC,QAAQ,CAAC,CAAC;IAA9B,YAA6B,CAAC,EAAE,aAAa,EAAI;IAEjD,gEAAgE;IAC1D,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM,EAAE,MAAM,GAAE,aAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAKhG;IAEK,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAIvF;IAEK,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,EAChB,MAAM,GAAE,kBAAuB,GAC9B,OAAO,CAAC,WAAW,EAAE,CAAC,CAKxB;CACF;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IAEvC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC,YAAY,OAAO,GAAE,aAAkB,EAItC;IAED,kEAAkE;IAClE,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAEzB;CACF"}
@@ -6,8 +6,32 @@
6
6
  // client.timeseries.currentMeasurement("BONN", "W")
7
7
  // client.timeseries.measurements("BONN", "W", { start: "P3D" })
8
8
  import { RequestEngine } from "./engine.js";
9
+ import { PegelError } from "./errors.js";
9
10
  const API = "/webservices/rest-api/v2";
10
- const enc = encodeURIComponent;
11
+ /**
12
+ * Station names, waters and ids are matched exactly by the API, which stores them
13
+ * composed (NFC): a decomposed umlaut ("KO" + U+0308 + "LN", as pasted from macOS
14
+ * file names or some PDFs) is a 404 / an empty list. Compose every such input.
15
+ * NFC, not NFKC: an id lookup must not rewrite compatibility characters.
16
+ */
17
+ function nfc(value) {
18
+ return value.normalize("NFC");
19
+ }
20
+ /**
21
+ * One URL path segment from a caller-supplied station or timeseries id. A blank
22
+ * value would build a different path (`stations/.json`, `stations//W.json`), and
23
+ * "." / ".." pass encodeURIComponent unchanged and are resolved by URL parsing
24
+ * (the engine's `buildUrl` refuses them as path segments too), so all are refused.
25
+ */
26
+ function enc(name, value) {
27
+ if (typeof value !== "string" || value.trim() === "") {
28
+ throw new PegelError(`Invalid ${name}: expected a non-empty string, got ${JSON.stringify(value)}.`);
29
+ }
30
+ if (value === "." || value === "..") {
31
+ throw new PegelError(`Invalid ${name} "${value}": "." and ".." cannot be used as an id.`);
32
+ }
33
+ return encodeURIComponent(nfc(value));
34
+ }
11
35
  /** Drop undefined values so only the parameters the caller set are sent. */
12
36
  function prune(params) {
13
37
  const out = {};
@@ -17,6 +41,20 @@ function prune(params) {
17
41
  }
18
42
  return out;
19
43
  }
44
+ /**
45
+ * The station include parameters. The API nests the current measurement and the
46
+ * gauge marks *inside* each timeseries, so without `includeTimeseries=true` it
47
+ * silently drops both. Asking for either therefore implies `includeTimeseries`
48
+ * unless the caller set it explicitly.
49
+ */
50
+ function stationIncludes(p) {
51
+ const nested = p.includeCurrentMeasurement === true || p.includeCharacteristicValues === true;
52
+ return prune({
53
+ includeTimeseries: p.includeTimeseries ?? (nested ? true : undefined),
54
+ includeCurrentMeasurement: p.includeCurrentMeasurement,
55
+ includeCharacteristicValues: p.includeCharacteristicValues,
56
+ });
57
+ }
20
58
  function includeQuery(p) {
21
59
  return prune({
22
60
  includeTimeseries: p.includeTimeseries,
@@ -32,17 +70,15 @@ class StationsResource {
32
70
  }
33
71
  list(params = {}) {
34
72
  const query = prune({
35
- ids: params.ids && params.ids.length > 0 ? params.ids.join(",") : undefined,
36
- waters: params.waters,
37
- fuzzyId: params.fuzzyId,
38
- includeTimeseries: params.includeTimeseries,
39
- includeCurrentMeasurement: params.includeCurrentMeasurement,
40
- includeCharacteristicValues: params.includeCharacteristicValues,
73
+ ids: params.ids && params.ids.length > 0 ? params.ids.map(nfc).join(",") : undefined,
74
+ waters: params.waters === undefined ? undefined : nfc(params.waters),
75
+ fuzzyId: params.fuzzyId === undefined ? undefined : nfc(params.fuzzyId),
76
+ ...stationIncludes(params),
41
77
  });
42
78
  return this.e.getJson(`${API}/stations.json`, query);
43
79
  }
44
- get(station, params = {}) {
45
- return this.e.getJson(`${API}/stations/${enc(station)}.json`, includeQuery(params));
80
+ async get(station, params = {}) {
81
+ return this.e.getJson(`${API}/stations/${enc("station", station)}.json`, stationIncludes(params));
46
82
  }
47
83
  }
48
84
  /** Timeseries: metadata, the current measurement, a window of measurements, gauge marks. */
@@ -52,14 +88,14 @@ class TimeseriesResource {
52
88
  this.e = e;
53
89
  }
54
90
  /** Timeseries metadata (e.g. "W" = water level, "Q" = flow). */
55
- get(station, timeseries = "W", params = {}) {
56
- return this.e.getJson(`${API}/stations/${enc(station)}/${enc(timeseries)}.json`, includeQuery(params));
91
+ async get(station, timeseries = "W", params = {}) {
92
+ return this.e.getJson(`${API}/stations/${enc("station", station)}/${enc("timeseries", timeseries)}.json`, includeQuery(params));
57
93
  }
58
- currentMeasurement(station, timeseries = "W") {
59
- return this.e.getJson(`${API}/stations/${enc(station)}/${enc(timeseries)}/currentmeasurement.json`);
94
+ async currentMeasurement(station, timeseries = "W") {
95
+ return this.e.getJson(`${API}/stations/${enc("station", station)}/${enc("timeseries", timeseries)}/currentmeasurement.json`);
60
96
  }
61
- measurements(station, timeseries = "W", params = {}) {
62
- return this.e.getJson(`${API}/stations/${enc(station)}/${enc(timeseries)}/measurements.json`, prune({ start: params.start, end: params.end }));
97
+ async measurements(station, timeseries = "W", params = {}) {
98
+ return this.e.getJson(`${API}/stations/${enc("station", station)}/${enc("timeseries", timeseries)}/measurements.json`, prune({ start: params.start, end: params.end }));
63
99
  }
64
100
  }
65
101
  export class PegelOnlineClient {