restura-cli 0.2.14
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 +177 -0
- package/dist/bundle.generated-SLCGKGZD.js +29 -0
- package/dist/chunk-JSBRDJBE.js +30 -0
- package/dist/index.js +5581 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# restura-cli
|
|
2
|
+
|
|
3
|
+
Run Restura API collections in CI — assert with scripts, get JUnit / HTML / JSON reports.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g restura-cli
|
|
9
|
+
# or, no install:
|
|
10
|
+
npx restura-cli run ./my-collection
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node.js 24+.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
Export a collection from the Restura app (File → Export → OpenCollection directory), then:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
restura run ./my-collection --reporter junit --reporter-output junit=results.xml
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Exit code is `0` when every request passed, `1` if any failed, `2` on internal errors (missing collection, bad flags).
|
|
24
|
+
|
|
25
|
+
## Supported collection formats
|
|
26
|
+
|
|
27
|
+
The loader auto-detects three layouts:
|
|
28
|
+
|
|
29
|
+
| Layout | Detected when… |
|
|
30
|
+
| ---------------------------------------- | --------------------------------------------------------------- |
|
|
31
|
+
| **OpenCollection directory** (preferred) | the target directory contains `opencollection.yml` (or `.yaml`) |
|
|
32
|
+
| **OpenCollection bundled file** | the target path ends in `.yaml`/`.yml` |
|
|
33
|
+
| **Legacy file-collection** (deprecated) | the target directory contains `_collection.yaml` |
|
|
34
|
+
|
|
35
|
+
The legacy format prints a stderr deprecation warning the first time it's loaded.
|
|
36
|
+
|
|
37
|
+
## Supported protocols
|
|
38
|
+
|
|
39
|
+
- **HTTP / REST** — full support
|
|
40
|
+
- **GraphQL** — runs as HTTP with body type `graphql`
|
|
41
|
+
- **gRPC** — via Connect protocol (JSON-encoded, no proto compilation needed)
|
|
42
|
+
- **SSE** — captures events for `--sse-duration` ms, or until `--sse-events N`
|
|
43
|
+
- **MCP** — single JSON-RPC POST per request
|
|
44
|
+
- **WebSocket** — standalone executor available; not yet wired into the dispatcher (see `executors/websocket.ts`)
|
|
45
|
+
|
|
46
|
+
Header-based auth (Bearer, Basic, API-key, OAuth2 access token) is applied to HTTP/GraphQL, gRPC (as metadata), SSE, and MCP requests. Wire-signed schemes (AWS SigV4, OAuth1, WSSE) are signed at the wire on the HTTP path. `x-www-form-urlencoded` bodies are sent for both inline (`raw`) and structured (OpenCollection field-array) forms; `multipart/form-data` and `protobuf` bodies are not yet supported by the CLI fetcher.
|
|
47
|
+
|
|
48
|
+
## CLI reference
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
restura run <collection> [options]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`<collection>` accepts a directory (any supported layout) or a bundled `.yaml`/`.yml` file.
|
|
55
|
+
|
|
56
|
+
| Flag | Default | Description |
|
|
57
|
+
| --------------------------- | ------------- | ---------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `--env <file>` | | JSON or YAML env file. `${VAR}` placeholders are expanded from `process.env`. |
|
|
59
|
+
| `--reporter <list>` | `live` | Comma-separated. Mix and match: `live`, `json`, `junit`, `html`. |
|
|
60
|
+
| `--output <file>` | | Shorthand for single file reporter. |
|
|
61
|
+
| `--reporter-output <kv...>` | | Per-reporter output: `--reporter-output junit=results.xml html=report.html`. |
|
|
62
|
+
| `--bail` | `false` | Stop on first failure. |
|
|
63
|
+
| `--timeout <ms>` | `30000` | Per-request timeout. |
|
|
64
|
+
| `--allow-localhost` | `false` | Permit requests to `localhost` / `127.0.0.1`. Off by default (SSRF guard). |
|
|
65
|
+
| `--folder <path>` | | Only run requests under this folder path (slash-joined). |
|
|
66
|
+
| `--include <pattern...>` | | Substring or glob (e.g. `users/*`). Repeatable. |
|
|
67
|
+
| `--exclude <pattern...>` | | Same syntax as `--include`. Applied after. |
|
|
68
|
+
| `--data <file>` | | CSV (with header row) or JSON array. Runs the collection once per row; row keys are exposed as vars. |
|
|
69
|
+
| `--max-iterations <n>` | | Cap iterations when a `--data` file is large. |
|
|
70
|
+
| `--retry <n>` | `0` | Retry attempts per failing request. |
|
|
71
|
+
| `--retry-on <list>` | `network,5xx` | Comma-separated triggers: `network`, `5xx`, `4xx`, or specific status codes (`429,503`). |
|
|
72
|
+
| `--sse-duration <ms>` | `5000` | How long to keep SSE streams open. |
|
|
73
|
+
| `--sse-events <n>` | | Stop SSE early after N events. |
|
|
74
|
+
| `--ws-duration <ms>` | `5000` | How long to keep WebSocket connections open. |
|
|
75
|
+
| `--ws-messages <n>` | | Stop WebSocket early after N messages. |
|
|
76
|
+
|
|
77
|
+
## Scripts and assertions
|
|
78
|
+
|
|
79
|
+
Pre-request and test scripts run in a sandboxed QuickJS WASM VM (no DOM, no filesystem, no network escape; 64 MB memory cap, 5 s sync / 30 s async execution timeout).
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
# request.http.yaml
|
|
83
|
+
name: Get user
|
|
84
|
+
method: GET
|
|
85
|
+
url: '{{API_BASE}}/users/1'
|
|
86
|
+
testScript: |
|
|
87
|
+
pm.test("status is 200", () => pm.response.to.have.status(200));
|
|
88
|
+
pm.test("response has name", () => {
|
|
89
|
+
pm.expect(pm.response.json()).to.have.property("name");
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
When a test script runs and defines any `pm.test(...)` assertion, those drive pass/fail. Otherwise pass/fail falls back to the transport outcome (HTTP 2xx, gRPC OK, etc.).
|
|
94
|
+
|
|
95
|
+
Variables set inside a script (`pm.environment.set('K', 'v')`) propagate to subsequent requests in the same run.
|
|
96
|
+
|
|
97
|
+
## Variables
|
|
98
|
+
|
|
99
|
+
Three layered sources, in order of precedence (later wins):
|
|
100
|
+
|
|
101
|
+
1. `--env` file
|
|
102
|
+
2. Collection variables (declared in `opencollection.yml` or `_collection.yaml`)
|
|
103
|
+
3. Iteration row (when `--data` is set)
|
|
104
|
+
|
|
105
|
+
Substitutions are `{{NAME}}`. Unknown vars are left in place so the upstream sees them and you notice the gap.
|
|
106
|
+
|
|
107
|
+
### Dynamic helpers
|
|
108
|
+
|
|
109
|
+
Postman-compatible `{{$random*}}` / `{{$timestamp}}` helpers are expanded after user var substitution:
|
|
110
|
+
|
|
111
|
+
| Helper | Example |
|
|
112
|
+
| ---------------------- | --------------------------- |
|
|
113
|
+
| `{{$randomUUID}}` | `f4d2e3...` |
|
|
114
|
+
| `{{$timestamp}}` | `1700000000` (unix seconds) |
|
|
115
|
+
| `{{$isoTimestamp}}` | `2026-05-22T13:42:00Z` |
|
|
116
|
+
| `{{$randomEmail}}` | `alice.42@example.com` |
|
|
117
|
+
| `{{$randomFirstName}}` | `Olivia` |
|
|
118
|
+
| `{{$randomIP}}` | `192.0.2.4` |
|
|
119
|
+
|
|
120
|
+
Full list in `src/lib/shared/dynamicVariables.ts`.
|
|
121
|
+
|
|
122
|
+
## Data-driven runs
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
restura run ./users-api --data ./users.csv --reporter junit --reporter-output junit=junit.xml
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```csv
|
|
129
|
+
# users.csv
|
|
130
|
+
username,role
|
|
131
|
+
alice,admin
|
|
132
|
+
bob,viewer
|
|
133
|
+
charlie,editor
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Each row exposes `username` and `role` as variables, overriding any same-named env or collection variable for that iteration only. JUnit testcase names carry an `[iter N]` suffix so each iteration is distinct in CI dashboards.
|
|
137
|
+
|
|
138
|
+
## Reporters
|
|
139
|
+
|
|
140
|
+
- **`live`** — coloured progress to stdout. Default.
|
|
141
|
+
- **`json`** — full `RunResult` dumped as JSON. Path required (`--output` or `--reporter-output json=...`).
|
|
142
|
+
- **`junit`** — JUnit XML for CI dashboards. One `<testcase>` per request.
|
|
143
|
+
- **`html`** — self-contained HTML page with embedded data + summary table.
|
|
144
|
+
|
|
145
|
+
Combine with a comma: `--reporter live,junit --reporter-output junit=results.xml`.
|
|
146
|
+
|
|
147
|
+
## Exit codes
|
|
148
|
+
|
|
149
|
+
| Code | Meaning |
|
|
150
|
+
| ---- | ------------------------------------------------------------------------------- |
|
|
151
|
+
| `0` | Every request passed AND at least one request ran |
|
|
152
|
+
| `1` | One or more requests failed or errored (or no requests matched after filtering) |
|
|
153
|
+
| `2` | Internal error: missing collection, bad reporter name, IO failure, … |
|
|
154
|
+
|
|
155
|
+
## Troubleshooting
|
|
156
|
+
|
|
157
|
+
- **`No recognised collection layout`** — your target directory needs one of `opencollection.yml`, `opencollection.yaml`, or `_collection.yaml`. Re-export from the Restura app if unsure.
|
|
158
|
+
- **`Invalid URL`** — the URL after `{{var}}` resolution isn't a valid absolute URL. Check that `--env` is loaded and your var names match.
|
|
159
|
+
- **`Localhost URLs are not allowed`** — add `--allow-localhost` for local upstreams. Off by default to prevent SSRF in shared CI.
|
|
160
|
+
- **gRPC requests return `UNKNOWN`** — the upstream likely doesn't speak Connect protocol. The CLI uses Connect-over-HTTP, not gRPC-over-HTTP/2 binary framing.
|
|
161
|
+
- **`auth uses a desktop-only secret handle…`** — your auth references a secret handle that only the desktop app can decrypt. The request is errored (not sent unauthenticated); re-export the collection with inline secret values for CI use.
|
|
162
|
+
|
|
163
|
+
## Development
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# from cli/
|
|
167
|
+
npm install
|
|
168
|
+
npm test # vitest
|
|
169
|
+
npm run type-check # tsc --noEmit
|
|
170
|
+
npm run build # tsup → dist/
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The CLI imports from the parent project at compile-time via path aliases (`@/`, `@shared/`); `cli/tsconfig.json` controls which parent modules participate in type-checking.
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT.
|