@maschinenlesbar.org/govdata-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 +172 -130
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,187 +1,229 @@
|
|
|
1
1
|
# govdata-cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
[](https://github.com/maschinenlesbar-org/govdata-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/maschinenlesbar-org/govdata-cli/actions/workflows/release.yml)
|
|
5
|
+
[](https://www.npmjs.com/package/@maschinenlesbar.org/govdata-cli)
|
|
6
|
+
|
|
7
|
+
Browse Germany's central open-data catalogue from your terminal. `govdata` is a
|
|
8
|
+
command-line tool over the [GovData CKAN Action API](https://www.govdata.de/)
|
|
9
|
+
(`ckan.govdata.de`) — the national portal that federates open datasets from
|
|
10
|
+
federal government, federal states and municipalities: search, inspect, filter
|
|
11
|
+
and pipe straight into [`jq`](https://jqlang.github.io/jq/).
|
|
12
|
+
|
|
13
|
+
- **Works out of the box** — no account, no API key, no configuration. Install
|
|
14
|
+
and explore.
|
|
15
|
+
- **Clean JSON output** — the CKAN envelope is unwrapped for you; `--compact`
|
|
16
|
+
for one-line/scripting.
|
|
17
|
+
- **Ten commands** — `search`, `package`, `packages`, `organizations`,
|
|
18
|
+
`organization`, `groups`, `group`, `tags`, `resource`, and a generic `action`
|
|
19
|
+
escape hatch.
|
|
20
|
+
- **Everything is open** — every dataset this tool reaches is publicly licensed;
|
|
21
|
+
nothing to register for.
|
|
22
|
+
|
|
23
|
+
> Want to use this as a TypeScript library or understand how it's built?
|
|
24
|
+
> See **[DEVELOPING.md](DEVELOPING.md)**.
|
|
17
25
|
|
|
18
26
|
## Install
|
|
19
27
|
|
|
20
28
|
```bash
|
|
21
|
-
npm
|
|
22
|
-
npm run build # compiles TypeScript to dist/
|
|
29
|
+
npm i -g @maschinenlesbar.org/govdata-cli
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
This installs the **`govdata`** command. Requires **Node.js 20+**.
|
|
33
|
+
|
|
34
|
+
Check it works:
|
|
26
35
|
|
|
27
36
|
```bash
|
|
28
|
-
node dist/src/cli/index.js --help
|
|
29
|
-
# or, after `npm link` / global install:
|
|
30
37
|
govdata --help
|
|
31
38
|
```
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
## Quickstart
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
No setup needed — the API is open and requires no key. Your first search:
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
```bash
|
|
45
|
+
govdata search Haushalt --rows 5
|
|
46
|
+
```
|
|
40
47
|
|
|
41
|
-
|
|
48
|
+
The result is unwrapped from CKAN's `{ help, success, result }` envelope — you
|
|
49
|
+
get the search object directly: `{ count, results, sort, … }`. Pull out just
|
|
50
|
+
the titles with `jq`:
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
| `--max-retries <n>` | Retries for transient `429`/`503` responses (default `2`) |
|
|
49
|
-
| `--max-response-bytes <n>` | Cap response body size in bytes (`0` = unlimited; default 100 MiB) |
|
|
50
|
-
| `--compact` | Print JSON on a single line |
|
|
52
|
+
```bash
|
|
53
|
+
govdata search Haushalt --rows 5 | jq '{count, titles: [.results[].title]}'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Take a name from those results and fetch the full dataset record:
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
```bash
|
|
59
|
+
govdata package luftqualitat
|
|
60
|
+
```
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
## Commands
|
|
56
63
|
|
|
57
64
|
```text
|
|
58
|
-
search [query] [
|
|
59
|
-
package <id>
|
|
60
|
-
packages [--limit] [--offset] list dataset names
|
|
61
|
-
organizations [--all-fields]
|
|
62
|
-
organization <id>
|
|
63
|
-
groups [--all-fields]
|
|
64
|
-
group <id>
|
|
65
|
-
tags [--query <substring>]
|
|
66
|
-
resource <id>
|
|
67
|
-
action <name> [--param key=value
|
|
65
|
+
search [query] [filters…] search datasets
|
|
66
|
+
package <id> show one dataset by id or name
|
|
67
|
+
packages [--limit <n>] [--offset <n>] list dataset names
|
|
68
|
+
organizations [--all-fields] list organizations (publishers)
|
|
69
|
+
organization <id> show one organization
|
|
70
|
+
groups [--all-fields] list groups (themes/categories)
|
|
71
|
+
group <id> show one group
|
|
72
|
+
tags [--query <substring>] list tags
|
|
73
|
+
resource <id> show one resource (distribution)
|
|
74
|
+
action <name> [--param key=value …] call any CKAN action (generic)
|
|
68
75
|
```
|
|
69
76
|
|
|
70
|
-
###
|
|
77
|
+
### `search` filters
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
| Flag | Meaning |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `[query]` | free-text Solr query, e.g. `Haushalt` or `title:Klimaschutz` |
|
|
82
|
+
| `--fq <filter>` | Solr filter query, e.g. `organization:destatis` (repeatable) |
|
|
83
|
+
| `--rows <n>` | max results to return |
|
|
84
|
+
| `--start <n>` | zero-based offset for paging |
|
|
85
|
+
| `--sort <expr>` | Solr sort expression, e.g. `metadata_modified desc` |
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
govdata search --fq organization:destatis --fq res_format:CSV
|
|
87
|
+
### `packages` flags
|
|
78
88
|
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
| Flag | Meaning |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| `--limit <n>` | max names to return |
|
|
92
|
+
| `--offset <n>` | number of records to skip |
|
|
81
93
|
|
|
82
|
-
|
|
83
|
-
govdata organizations
|
|
94
|
+
### `organizations` / `groups` flag
|
|
84
95
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
96
|
+
| Flag | Meaning |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `--all-fields` | return full objects instead of bare names |
|
|
99
|
+
|
|
100
|
+
### `tags` flag
|
|
101
|
+
|
|
102
|
+
| Flag | Meaning |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `--query <substring>` | filter tags by substring |
|
|
88
105
|
|
|
89
|
-
|
|
106
|
+
### `action` flag
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
| Flag | Meaning |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| `--param <key=value>` | query parameter (repeatable; duplicate keys are rejected) |
|
|
92
111
|
|
|
93
|
-
|
|
112
|
+
The **[Glossary](GLOSSARY.md)** decodes every CKAN term and search-parameter
|
|
113
|
+
name.
|
|
94
114
|
|
|
95
|
-
|
|
96
|
-
import { GovDataClient, GovDataError } from "@maschinenlesbar.org/govdata-cli";
|
|
115
|
+
## Common tasks
|
|
97
116
|
|
|
98
|
-
|
|
117
|
+
A few recipes to get going — see **[Usage.md](Usage.md)** for the full,
|
|
118
|
+
use-case-driven set.
|
|
99
119
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
```bash
|
|
121
|
+
# Newest datasets first
|
|
122
|
+
govdata search Klima --rows 10 --sort "metadata_modified desc"
|
|
103
123
|
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
# Filter by publisher and file format
|
|
125
|
+
govdata search --fq organization:destatis --fq res_format:CSV
|
|
106
126
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
```
|
|
127
|
+
# Full dataset with all its resources (distributions)
|
|
128
|
+
govdata package luftqualitat | jq '.resources[] | {name, format, url}'
|
|
129
|
+
|
|
130
|
+
# All data publishers (short names)
|
|
131
|
+
govdata organizations
|
|
113
132
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
transport: customTransport, // inject your own HTTP transport
|
|
124
|
-
});
|
|
133
|
+
# Full publisher objects, then drill into one
|
|
134
|
+
govdata organizations --all-fields | jq '.[] | {name, title, packages: .package_count}'
|
|
135
|
+
govdata organization statistisches-bundesamt | jq '{title, package_count}'
|
|
136
|
+
|
|
137
|
+
# Tags matching a substring
|
|
138
|
+
govdata tags --query energie
|
|
139
|
+
|
|
140
|
+
# Any CKAN action not covered by a dedicated command
|
|
141
|
+
govdata action package_search --param q=Verkehr --param rows=3
|
|
125
142
|
```
|
|
126
143
|
|
|
127
|
-
|
|
144
|
+
## Output & scripting
|
|
128
145
|
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
Every command prints the **unwrapped `result`** as pretty JSON to stdout.
|
|
147
|
+
Errors and diagnostics go to stderr, so piping stdout into `jq` stays clean.
|
|
131
148
|
|
|
132
|
-
|
|
149
|
+
```bash
|
|
150
|
+
# Total datasets in the catalogue
|
|
151
|
+
govdata action package_search --param rows=0 | jq '.count'
|
|
133
152
|
|
|
134
|
-
|
|
153
|
+
# Resource format and download URL from a dataset
|
|
154
|
+
govdata package luftqualitat | jq '.resources[] | {format, url}'
|
|
135
155
|
|
|
156
|
+
# Discover a valid dataset name from a search hit
|
|
157
|
+
govdata search Luftqualität --rows 1 | jq -r '.results[0].name'
|
|
136
158
|
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
engine.ts # URL building, retry/backoff, redirects, JSON decoding, error mapping
|
|
143
|
-
errors.ts # GovDataError / GovDataApiError / GovDataNetworkError / GovDataParseError
|
|
144
|
-
client.ts # GovDataClient — CKAN actions over the engine (with result-unwrapping)
|
|
145
|
-
cli/
|
|
146
|
-
io.ts # injectable I/O seam (stdout/stderr)
|
|
147
|
-
shared.ts # option parsers, global-option resolver, JSON renderer
|
|
148
|
-
commands/ # search / package / organizations / groups / tags / resource / action
|
|
149
|
-
program.ts # assembles the commander program from injectable deps
|
|
150
|
-
run.ts # parses argv -> exit code (no process.exit; testable)
|
|
151
|
-
index.ts # #! bin shim
|
|
159
|
+
|
|
160
|
+
Use `--compact` for single-line JSON in pipelines and logs:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
govdata --compact search Haushalt --rows 5 | jq -c '.results[].title'
|
|
152
164
|
```
|
|
153
165
|
|
|
154
|
-
**
|
|
166
|
+
`--compact` (and every global option) works **before or after** the command —
|
|
167
|
+
both `govdata --compact search …` and `govdata search … --compact` do the same
|
|
168
|
+
thing.
|
|
155
169
|
|
|
156
|
-
|
|
157
|
-
uses `node:http`/`node:https`; tests inject a mock. This keeps the client free of any HTTP framework.
|
|
158
|
-
- The client unwraps CKAN's `{ help, success, result }` envelope and raises `GovDataError`
|
|
159
|
-
when `success` is false, so callers work directly with `result`.
|
|
160
|
-
- A generic `action(name, params)` exposes every read action even where there is no typed convenience method. The action name is validated against `^[a-z0-9_]+$` and URL-encoded, so it cannot inject extra path segments, query string, or fragments into the request URL.
|
|
161
|
-
- Redirects are followed up to `maxRedirects`; if a redirect crosses origin, the request headers are dropped so nothing (e.g. a future auth/cookie header) leaks to another host.
|
|
170
|
+
**Exit codes** make the CLI easy to use in scripts:
|
|
162
171
|
|
|
163
|
-
|
|
172
|
+
| Code | Meaning |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `0` | success (also `--help` / `--version`) |
|
|
175
|
+
| `4` | dataset/resource not found (`404`) |
|
|
176
|
+
| `1` | any other error — bad usage, CKAN `success:false`, network failure |
|
|
164
177
|
|
|
165
|
-
##
|
|
178
|
+
## Troubleshooting
|
|
166
179
|
|
|
167
|
-
|
|
168
|
-
npm
|
|
169
|
-
|
|
180
|
+
- **`command not found: govdata`** — the global npm bin directory isn't on your
|
|
181
|
+
`PATH`. Run `npm bin -g` to find it and add it, or run via
|
|
182
|
+
`npx @maschinenlesbar.org/govdata-cli …`.
|
|
183
|
+
- **Exit `4` / "not found"** — the dataset or resource id doesn't exist or has
|
|
184
|
+
been removed. Re-run a `search` to get a fresh name/id.
|
|
185
|
+
- **Exit `1` / CKAN `success:false`** — the catalogue rejected the request
|
|
186
|
+
(malformed filter, unknown action name, etc.). Check your `--fq` syntax or
|
|
187
|
+
`--param` values.
|
|
188
|
+
- **Network failure / timeout** — connectivity or a slow server. Try again, or
|
|
189
|
+
raise the limit with `--timeout 60000`.
|
|
190
|
+
- **Empty `results`** — the search matched nothing; broaden the keyword, drop
|
|
191
|
+
an `--fq` filter, or check spelling.
|
|
192
|
+
|
|
193
|
+
## Global options
|
|
194
|
+
|
|
195
|
+
These apply to every command and may be given before *or* after it:
|
|
196
|
+
|
|
197
|
+
| Option | Description |
|
|
198
|
+
| --- | --- |
|
|
199
|
+
| `-V, --version` | Print the version number |
|
|
200
|
+
| `-h, --help` | Show help for the program or a command |
|
|
201
|
+
| `--compact` | Print JSON on a single line instead of pretty-printed |
|
|
202
|
+
| `--base-url <url>` | API base URL (default `https://ckan.govdata.de`) |
|
|
203
|
+
| `--timeout <ms>` | Per-request timeout (default `30000`) |
|
|
204
|
+
| `--user-agent <ua>` | `User-Agent` header value |
|
|
205
|
+
| `--max-retries <n>` | Retries for transient `429`/`503` responses (default `2`) |
|
|
206
|
+
| `--max-response-bytes <n>` | Cap response body size in bytes (`0` = unlimited; default 100 MiB) |
|
|
207
|
+
|
|
208
|
+
## Learn more
|
|
170
209
|
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
210
|
+
- **[Usage.md](Usage.md)** — full use-case-driven cookbook.
|
|
211
|
+
- **[GLOSSARY.md](GLOSSARY.md)** — every CKAN term, search parameter and domain
|
|
212
|
+
concept explained.
|
|
213
|
+
- **[DEVELOPING.md](DEVELOPING.md)** — TypeScript library usage, architecture,
|
|
214
|
+
testing, CI.
|
|
215
|
+
- **[SKILLS.md](SKILLS.md)** — Claude Code Agent Skills bundled with this repo
|
|
216
|
+
(dataset finder, catalogue stats, resource harvest), installable as a plugin.
|
|
176
217
|
|
|
177
|
-
##
|
|
218
|
+
## Data license
|
|
178
219
|
|
|
179
|
-
|
|
220
|
+
This CLI is a **client** — it accesses data it does not own or redistribute. The
|
|
221
|
+
upstream data is © its provider and licensed **separately from this tool's code**.
|
|
222
|
+
See **[DATA_LICENSE.md](DATA_LICENSE.md)**.
|
|
180
223
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
- **docs.yml** — build TypeDoc API docs and deploy to GitHub Pages on each `v*` tag.
|
|
224
|
+
> **GovData** — catalogue *metadata* is Datenlizenz Deutschland **Zero** 2.0 (≈ CC0,
|
|
225
|
+
> no attribution). Each linked **dataset has its own license** set by its publisher
|
|
226
|
+
> — always check the dataset's `dct:license` before reusing its contents.
|
|
185
227
|
|
|
186
228
|
## License
|
|
187
229
|
|