@atrahasis/cli 1.0.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.
- package/README.md +389 -0
- package/bin/atra.js +19 -0
- package/package.json +20 -0
- package/scripts/install.js +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# atra
|
|
2
|
+
|
|
3
|
+
**Atrahasis CLI** - atra
|
|
4
|
+
|
|
5
|
+
A fast, modern HTTP client CLI built with Rust. Supports HTTP/1.1, HTTP/2, and HTTP/3 (QUIC) with built-in load testing, flow runner, assertions, and detailed request tracing.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
**npm**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @atrahasis/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Homebrew**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
brew install atrahasisdev/tap/atra
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**curl**
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -sSL https://cli.atrahasis.dev | sh
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**wget**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
wget -qO- https://cli.atrahasis.dev | sh
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**PowerShell (Windows)**
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
irm https://cli.atrahasis.dev | iex
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Verify your installation:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
atra --version
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Simple GET request
|
|
49
|
+
atra GET https://api.example.com/users
|
|
50
|
+
|
|
51
|
+
# POST with JSON body
|
|
52
|
+
atra POST https://api.example.com/users name:John age:25
|
|
53
|
+
|
|
54
|
+
# POST with raw JSON
|
|
55
|
+
atra POST https://api.example.com/users \
|
|
56
|
+
-H "Content-Type: application/json" \
|
|
57
|
+
-d '{"name": "John", "age": 25}'
|
|
58
|
+
|
|
59
|
+
# Headers and auth
|
|
60
|
+
atra GET https://api.example.com/users -H "Accept: application/json" --bearer my-token
|
|
61
|
+
|
|
62
|
+
# Form data
|
|
63
|
+
atra POST https://api.example.com/upload -F "file=@photo.jpg" -F "caption=Hello"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Request Tracing (`--trace`)
|
|
67
|
+
|
|
68
|
+
Get a full timing breakdown of every phase in the request lifecycle:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
atra GET https://api.example.com --trace
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Response Time 652.27 ms
|
|
76
|
+
|
|
77
|
+
Prepare █ 6 µs
|
|
78
|
+
DNS Lookup █ 3.47 ms
|
|
79
|
+
TCP Handshake ██████ 160.91 ms
|
|
80
|
+
TLS Handshake ██████████████ 326.10 ms
|
|
81
|
+
Request Send █ 710 µs
|
|
82
|
+
Server Response ███████ 164.51 ms
|
|
83
|
+
Download 31 µs
|
|
84
|
+
Processing 1 µs
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use `-t` as shorthand:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
atra GET https://api.example.com -t
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Combine with verbose mode to see full request/response details alongside timing:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
atra GET https://api.example.com -t -v
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## HTTP/3 (QUIC)
|
|
100
|
+
|
|
101
|
+
atra has native HTTP/3 support via QUIC - no extra configuration needed:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Force HTTP/3
|
|
105
|
+
atra GET https://api.example.com --http3
|
|
106
|
+
|
|
107
|
+
# Force HTTP/2
|
|
108
|
+
atra GET https://api.example.com --http2
|
|
109
|
+
|
|
110
|
+
# Force HTTP/1.1
|
|
111
|
+
atra GET https://api.example.com --http1.1
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
When no protocol is forced, atra automatically negotiates the best available protocol and pools connections for reuse.
|
|
115
|
+
|
|
116
|
+
## Assertions
|
|
117
|
+
|
|
118
|
+
Validate responses directly from the command line. Exit code 1 on failure - perfect for CI/CD:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Status code
|
|
122
|
+
atra GET https://api.example.com --assert "status equals 200"
|
|
123
|
+
|
|
124
|
+
# Response time
|
|
125
|
+
atra GET https://api.example.com -a "response_time less_than 500"
|
|
126
|
+
|
|
127
|
+
# Body content
|
|
128
|
+
atra GET https://api.example.com -a "body contains success"
|
|
129
|
+
|
|
130
|
+
# JSON path
|
|
131
|
+
atra GET https://api.example.com -a "$.data.id exists"
|
|
132
|
+
atra GET https://api.example.com -a "$.users[0].name equals John"
|
|
133
|
+
|
|
134
|
+
# Headers
|
|
135
|
+
atra GET https://api.example.com -a "header Content-Type contains json"
|
|
136
|
+
|
|
137
|
+
# Multiple assertions
|
|
138
|
+
atra GET https://api.example.com \
|
|
139
|
+
-a "status equals 200" \
|
|
140
|
+
-a "response_time less_than 1000" \
|
|
141
|
+
-a "body contains users"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Assertion Targets**
|
|
145
|
+
|
|
146
|
+
| Target | Syntax | Description |
|
|
147
|
+
|--------|--------|-------------|
|
|
148
|
+
| `status` | `status operator value` | HTTP status code (e.g., 200, 404, 500) |
|
|
149
|
+
| `response_time` | `response_time operator ms` | Response time in milliseconds |
|
|
150
|
+
| `header` | `header name operator value` | Response header value (case-insensitive name) |
|
|
151
|
+
| `body` | `body operator value` | Full response body as string |
|
|
152
|
+
| `$.` | `$.path operator value` | JSON path - dot notation with array indexing (e.g., `$.users[0].name`) |
|
|
153
|
+
|
|
154
|
+
**Operators**
|
|
155
|
+
|
|
156
|
+
Each operator has short and long forms. Use whichever feels more natural.
|
|
157
|
+
|
|
158
|
+
| Short | Long | Description |
|
|
159
|
+
|-------|------|-------------|
|
|
160
|
+
| `eq` | `equals` | Exact match |
|
|
161
|
+
| `neq` | `not_equals` | Not equal |
|
|
162
|
+
| `gt` | `greater_than` | Numeric greater than |
|
|
163
|
+
| `lt` | `less_than` | Numeric less than |
|
|
164
|
+
| | `contains` | String contains |
|
|
165
|
+
| | `not_contains` | String does not contain |
|
|
166
|
+
| | `exists` | Value exists (not null) |
|
|
167
|
+
| | `not_exists` | Value is null or missing |
|
|
168
|
+
| | `is_empty` | Empty string, array, or object |
|
|
169
|
+
| | `is_not_empty` | Non-empty value |
|
|
170
|
+
| | `matches_regex` | Regex pattern match |
|
|
171
|
+
| | `is_type` | Check JSON type (string, number, boolean, array, object, null) |
|
|
172
|
+
|
|
173
|
+
**Short form examples:**
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
atra GET https://api.example.com -a "status eq 200"
|
|
177
|
+
atra GET https://api.example.com -a "response_time lt 500"
|
|
178
|
+
atra GET https://api.example.com -a "$.data.count gt 0"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Random Data Generation
|
|
182
|
+
|
|
183
|
+
Generate dynamic test data with 25+ built-in generators:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Random email and UUID
|
|
187
|
+
atra POST https://api.example.com/users \
|
|
188
|
+
'{"email": "{{random.email}}", "id": "{{random.uuid}}"}'
|
|
189
|
+
|
|
190
|
+
# Random string with length
|
|
191
|
+
atra POST https://api.example.com/data name:"{{random.string(20)}}"
|
|
192
|
+
|
|
193
|
+
# Random number in range
|
|
194
|
+
atra POST https://api.example.com/data score:"{{random.number(1,100)}}"
|
|
195
|
+
|
|
196
|
+
# Pick from a list
|
|
197
|
+
atra POST https://api.example.com/data color:"{{random.enum(red,green,blue)}}"
|
|
198
|
+
|
|
199
|
+
# Custom pattern
|
|
200
|
+
atra POST https://api.example.com/data code:"{{random.custom([A-Z]{3}-\d{4})}}"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Available generators: `uuid`, `email`, `name`, `string`, `number`, `boolean`, `date`, `ip`, `slug`, `url`, `phone`, and more.
|
|
204
|
+
|
|
205
|
+
## Flow Runner
|
|
206
|
+
|
|
207
|
+
Execute sequential API call chains defined in `.flow.json` files. Supports variable extraction, pre/post scripts, assertions, and retry logic.
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Run all flows in a directory
|
|
211
|
+
atra run api-tests
|
|
212
|
+
|
|
213
|
+
# Run a specific flow
|
|
214
|
+
atra run api-tests -f user-registration
|
|
215
|
+
|
|
216
|
+
# Run with environment
|
|
217
|
+
atra run api-tests -f user-registration -e dev
|
|
218
|
+
|
|
219
|
+
# Sequential iterations (5 times)
|
|
220
|
+
atra run api-tests -f user-registration -i 5
|
|
221
|
+
|
|
222
|
+
# Parallel execution (3 workers)
|
|
223
|
+
atra run api-tests -f user-registration -p 3
|
|
224
|
+
|
|
225
|
+
# Stop on first failure
|
|
226
|
+
atra run api-tests -f user-registration -c
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If you are already inside the flow directory:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
atra run
|
|
233
|
+
atra run -f flow-name
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Flow Runner Flags**
|
|
237
|
+
|
|
238
|
+
| Flag | Alias | Description |
|
|
239
|
+
|------|-------|-------------|
|
|
240
|
+
| `-f` | `--flow` | Flow names (comma-separated) |
|
|
241
|
+
| `-e` | `--env` | Environment name |
|
|
242
|
+
| `-i` | `--iterations` | Iteration count (default: 1) |
|
|
243
|
+
| `-p` | `--parallel` | Parallel worker count (default: 1) |
|
|
244
|
+
| `-c` | `--stop-on-failure` | Stop on first failure |
|
|
245
|
+
|
|
246
|
+
**Variable Types**
|
|
247
|
+
|
|
248
|
+
- `{{flow.varName}}` - Flow variables - carry data between steps
|
|
249
|
+
- `{{varName}}` - Environment variables
|
|
250
|
+
- `{{random.type}}` - Random value generated on each use
|
|
251
|
+
|
|
252
|
+
**Exit Codes:** `0` = all steps and assertions passed, `1` = failure
|
|
253
|
+
|
|
254
|
+
Features a live terminal dashboard with step-by-step progress, response times, assertion results, and anomaly detection.
|
|
255
|
+
|
|
256
|
+
## Load Testing
|
|
257
|
+
|
|
258
|
+
Run load tests from `.spec.json` files with virtual users, stages, and thresholds.
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# Run all specs in a directory
|
|
262
|
+
atra run spec-folder
|
|
263
|
+
|
|
264
|
+
# Run specific specs
|
|
265
|
+
atra run spec-folder -s user-api,auth-api
|
|
266
|
+
|
|
267
|
+
# Run with environment
|
|
268
|
+
atra run spec-folder -s user-api -e staging
|
|
269
|
+
|
|
270
|
+
# Stress test
|
|
271
|
+
atra run spec-folder -s user-api -t stress
|
|
272
|
+
|
|
273
|
+
# Spike test
|
|
274
|
+
atra run spec-folder -s user-api -t spike
|
|
275
|
+
|
|
276
|
+
# Soak test
|
|
277
|
+
atra run spec-folder -s user-api -t soak
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Test Types**
|
|
281
|
+
|
|
282
|
+
| Type | VUs | Ramp | Duration | Purpose |
|
|
283
|
+
|------|-----|------|----------|---------|
|
|
284
|
+
| `load` (default) | 50 | 30s | 60s | Gradual ramp up, sustained load, gradual ramp down |
|
|
285
|
+
| `stress` | 200 | 10s | 60s | Aggressive increase to find breaking points |
|
|
286
|
+
| `spike` | 300 | 2s | 30s | Sudden spike to high load |
|
|
287
|
+
| `soak` | 30 | 30s | 300s | Long duration with low, steady load |
|
|
288
|
+
| `custom` | Custom | Custom | Custom | User-defined stages |
|
|
289
|
+
|
|
290
|
+
**Load Test Flags**
|
|
291
|
+
|
|
292
|
+
| Flag | Alias | Description |
|
|
293
|
+
|------|-------|-------------|
|
|
294
|
+
| `-s` | `--spec` | Spec names (comma-separated) |
|
|
295
|
+
| `-t` | `--type` | Test type |
|
|
296
|
+
| `-e` | `--env` | Environment name |
|
|
297
|
+
|
|
298
|
+
Includes a real-time terminal dashboard with live charts, response time percentiles, error tracking, and threshold monitoring.
|
|
299
|
+
|
|
300
|
+
**Report Formats:** HTML, PDF, OpenTelemetry JSON
|
|
301
|
+
|
|
302
|
+
## CI/CD
|
|
303
|
+
|
|
304
|
+
atra works in any CI/CD pipeline. Assertions return exit code 1 on failure.
|
|
305
|
+
|
|
306
|
+
**GitHub Actions**
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
- name: API Health Check
|
|
310
|
+
run: |
|
|
311
|
+
curl -sSL https://cli.atrahasis.dev | sh
|
|
312
|
+
atra GET https://api.example.com \
|
|
313
|
+
-a "status eq 200" \
|
|
314
|
+
-a "response_time lt 2000"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**With npm/npx (no install needed)**
|
|
318
|
+
|
|
319
|
+
```yaml
|
|
320
|
+
- name: API Health Check
|
|
321
|
+
run: npx --yes @atrahasis/cli GET https://api.example.com -a "status eq 200"
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**GitHub Actions (Windows)**
|
|
325
|
+
|
|
326
|
+
```yaml
|
|
327
|
+
- name: API Health Check
|
|
328
|
+
shell: pwsh
|
|
329
|
+
run: |
|
|
330
|
+
irm https://cli.atrahasis.dev | iex
|
|
331
|
+
atra GET https://api.example.com -a "status eq 200"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**GitLab CI**
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
api-test:
|
|
338
|
+
script:
|
|
339
|
+
- curl -sSL https://cli.atrahasis.dev | sh
|
|
340
|
+
- atra GET https://api.example.com -a "status eq 200"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Run flow tests in CI**
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
- name: Run API Flow Tests
|
|
347
|
+
run: |
|
|
348
|
+
curl -sSL https://cli.atrahasis.dev | sh
|
|
349
|
+
atra run ./tests -f smoke-test -e ci
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Additional Features
|
|
353
|
+
|
|
354
|
+
| Feature | Flag |
|
|
355
|
+
|---------|------|
|
|
356
|
+
| Follow redirects | `-L` |
|
|
357
|
+
| Timeout | `-m 30` |
|
|
358
|
+
| Retry on failure | `--retry 3` |
|
|
359
|
+
| Skip TLS verification | `-k` |
|
|
360
|
+
| Basic auth | `-u user:pass` |
|
|
361
|
+
| Bearer token | `--bearer token` |
|
|
362
|
+
| OAuth 2.0 | `--oauth2 flow:url:id:secret` |
|
|
363
|
+
| Download file | `-D output.zip` |
|
|
364
|
+
| Cookie support | `-b "key=value"` |
|
|
365
|
+
| Named sessions | `-N my-session` |
|
|
366
|
+
| Verbose output | `-v` |
|
|
367
|
+
| JSON output | `--json` |
|
|
368
|
+
| Dry run | `-r` |
|
|
369
|
+
| Certificate info | `-C` |
|
|
370
|
+
| Silent mode | `-s` |
|
|
371
|
+
|
|
372
|
+
## Platform Support
|
|
373
|
+
|
|
374
|
+
| Platform | Architecture | Status |
|
|
375
|
+
|----------|-------------|--------|
|
|
376
|
+
| macOS | Apple Silicon (arm64) | Available |
|
|
377
|
+
| macOS | Intel (x86_64) | Available |
|
|
378
|
+
| Linux | arm64 | Available |
|
|
379
|
+
| Linux | x86_64 | Available |
|
|
380
|
+
| Windows | x86_64 | Available |
|
|
381
|
+
|
|
382
|
+
## Links
|
|
383
|
+
|
|
384
|
+
- [Atrahasis](https://atrahasis.dev)
|
|
385
|
+
- [atra Documentation](https://atrahasis.dev/cli)
|
|
386
|
+
|
|
387
|
+
## License
|
|
388
|
+
|
|
389
|
+
Proprietary - Atrahasis
|
package/bin/atra.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execFileSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
8
|
+
const binPath = path.join(__dirname, "atra-native" + ext);
|
|
9
|
+
|
|
10
|
+
if (!fs.existsSync(binPath)) {
|
|
11
|
+
console.error("atra binary not found. Try reinstalling: npm install -g @atrahasis/cli");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
17
|
+
} catch (err) {
|
|
18
|
+
process.exit(err.status || 1);
|
|
19
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atrahasis/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A fast, modern HTTP client CLI with load testing and flow runner",
|
|
5
|
+
"bin": {
|
|
6
|
+
"atra": "bin/atra.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node scripts/install.js"
|
|
10
|
+
},
|
|
11
|
+
"os": ["darwin", "linux", "win32"],
|
|
12
|
+
"keywords": ["http", "http-client", "rest-client", "cli", "api", "api-testing", "load-testing", "stress-test", "flow-runner", "http3", "quic", "assertions", "workflow", "runner"],
|
|
13
|
+
"author": "Atrahasis",
|
|
14
|
+
"license": "Proprietary",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/atrahasisdev/cli-releases.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://atrahasis.dev/cli"
|
|
20
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const { execFileSync } = require("child_process");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const https = require("https");
|
|
6
|
+
|
|
7
|
+
const REPO = "atrahasisdev/cli-releases";
|
|
8
|
+
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
9
|
+
const IS_WIN = os.platform() === "win32";
|
|
10
|
+
const BIN_NAME = IS_WIN ? "atra-native.exe" : "atra-native";
|
|
11
|
+
const BIN_PATH = path.join(BIN_DIR, BIN_NAME);
|
|
12
|
+
|
|
13
|
+
function getPlatform() {
|
|
14
|
+
const platform = os.platform();
|
|
15
|
+
const arch = os.arch();
|
|
16
|
+
|
|
17
|
+
const platformMap = {
|
|
18
|
+
darwin: "apple-darwin",
|
|
19
|
+
linux: "unknown-linux-gnu",
|
|
20
|
+
win32: "pc-windows-msvc",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const archMap = {
|
|
24
|
+
x64: "x86_64",
|
|
25
|
+
arm64: "aarch64",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const osTarget = platformMap[platform];
|
|
29
|
+
const archTarget = archMap[arch];
|
|
30
|
+
|
|
31
|
+
if (!osTarget || !archTarget) {
|
|
32
|
+
console.error(`Unsupported platform: ${platform}-${arch}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { osTarget, archTarget, isWindows: IS_WIN };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function httpsGet(url) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
https.get(url, { headers: { "User-Agent": "atrahasis-npm" } }, (res) => {
|
|
42
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
43
|
+
return httpsGet(res.headers.location).then(resolve).catch(reject);
|
|
44
|
+
}
|
|
45
|
+
const chunks = [];
|
|
46
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
47
|
+
res.on("end", () => resolve({ statusCode: res.statusCode, body: Buffer.concat(chunks) }));
|
|
48
|
+
res.on("error", reject);
|
|
49
|
+
}).on("error", reject);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function getLatestVersion() {
|
|
54
|
+
const res = await httpsGet(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
55
|
+
const data = JSON.parse(res.body.toString());
|
|
56
|
+
return data.tag_name;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function downloadBinary(version, archTarget, osTarget, isWindows) {
|
|
60
|
+
const ext = isWindows ? "zip" : "tar.gz";
|
|
61
|
+
const filename = `atra-${archTarget}-${osTarget}.${ext}`;
|
|
62
|
+
const url = `https://github.com/${REPO}/releases/download/${version}/${filename}`;
|
|
63
|
+
|
|
64
|
+
console.log(`Downloading atra ${version} for ${archTarget}-${osTarget}...`);
|
|
65
|
+
|
|
66
|
+
const res = await httpsGet(url);
|
|
67
|
+
if (res.statusCode !== 200) {
|
|
68
|
+
console.error(`Download failed with status ${res.statusCode}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const tmpFile = path.join(os.tmpdir(), filename);
|
|
73
|
+
fs.writeFileSync(tmpFile, res.body);
|
|
74
|
+
|
|
75
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
76
|
+
|
|
77
|
+
if (isWindows) {
|
|
78
|
+
execFileSync("powershell", ["-Command", `Expand-Archive -Path '${tmpFile}' -DestinationPath '${BIN_DIR}' -Force`], { stdio: "pipe" });
|
|
79
|
+
fs.renameSync(path.join(BIN_DIR, "atra.exe"), BIN_PATH);
|
|
80
|
+
} else {
|
|
81
|
+
execFileSync("tar", ["-xzf", tmpFile, "-C", BIN_DIR], { stdio: "pipe" });
|
|
82
|
+
fs.renameSync(path.join(BIN_DIR, "atra"), BIN_PATH);
|
|
83
|
+
fs.chmodSync(BIN_PATH, 0o755);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fs.unlinkSync(tmpFile);
|
|
87
|
+
console.log(`Successfully installed atra ${version}!`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function main() {
|
|
91
|
+
const { osTarget, archTarget, isWindows } = getPlatform();
|
|
92
|
+
const version = await getLatestVersion();
|
|
93
|
+
await downloadBinary(version, archTarget, osTarget, isWindows);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
main().catch((err) => {
|
|
97
|
+
console.error("Installation failed:", err.message);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|