@umeshindu222/apisnap 1.2.1 → 1.2.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 +99 -5
- package/apisnaprc.schema.json +128 -0
- package/dist/core/runner.js +640 -178
- package/dist/core/runner.js.map +1 -1
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +6 -4
- package/dist/middleware/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
<img width="4368" height="2112" alt="Group 1" src="https://github.com/user-attachments/assets/c162b436-1c64-470e-9f41-e5ceb09a31d4" />
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
## Quick start
|
|
4
6
|
|
|
@@ -25,6 +27,7 @@ apisnap.init(app); // ← must be AFTER your routes
|
|
|
25
27
|
|
|
26
28
|
[](https://www.npmjs.com/package/@umeshindu222/apisnap)
|
|
27
29
|
[](https://opensource.org/licenses/MIT)
|
|
30
|
+
[](https://socket.dev/npm/package/%40umeshindu222%2Fapisnap)
|
|
28
31
|
|
|
29
32
|
---
|
|
30
33
|
|
|
@@ -46,10 +49,16 @@ One command. Every route. Instant results.
|
|
|
46
49
|
- **Auth Hints** - tells you exactly how to fix 401/403 errors
|
|
47
50
|
- **Slow Route Detection** - flags endpoints that are too slow
|
|
48
51
|
- **Retry Logic** - auto-retries failed requests
|
|
52
|
+
- **Rate-limit Backoff** - honors `429 Retry-After` and retries automatically
|
|
49
53
|
- **HTML Reports** - beautiful visual reports you can share
|
|
50
54
|
- **JSON Export** - structured output for CI/CD pipelines
|
|
51
55
|
- **Config File** - save your settings so you don't retype every time
|
|
52
56
|
- **Method Filter** - test only GET, POST, DELETE etc.
|
|
57
|
+
- **Path Filter + Dry Run** - target a route subset and preview without requests
|
|
58
|
+
- **OpenAPI Discovery** - load routes from an OpenAPI JSON spec
|
|
59
|
+
- **Baseline Diffing** - compare against saved runs and fail on regressions
|
|
60
|
+
- **Latency Percentiles** - p50 / p95 / p99 in terminal and reports
|
|
61
|
+
- **Doctor Command** - quick setup diagnostics
|
|
53
62
|
- **Smart Path Params** - auto-replaces `:id`, `:slug`, `:uuid` with safe defaults
|
|
54
63
|
- **Express v4 & v5** - works with both versions
|
|
55
64
|
|
|
@@ -315,15 +324,45 @@ APISnap reads the config file automatically.
|
|
|
315
324
|
|
|
316
325
|
> ⚠️ **Add `.apisnaprc.json` to your `.gitignore`** so your token is never committed to GitHub.
|
|
317
326
|
|
|
327
|
+
### Config Schema + Secrets
|
|
328
|
+
|
|
329
|
+
Use the bundled schema for autocomplete and validation:
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"$schema": "./apisnaprc.schema.json"
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
You can reference environment variables anywhere in config values:
|
|
338
|
+
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"headers": [
|
|
342
|
+
"Authorization: Bearer $API_TOKEN"
|
|
343
|
+
],
|
|
344
|
+
"authFlow": {
|
|
345
|
+
"url": "/auth/login",
|
|
346
|
+
"body": {
|
|
347
|
+
"username": "$API_USER",
|
|
348
|
+
"password": "$API_PASSWORD"
|
|
349
|
+
},
|
|
350
|
+
"tokenPath": "token"
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
318
355
|
### Full Config File Options
|
|
319
356
|
|
|
320
357
|
```json
|
|
321
358
|
{
|
|
359
|
+
"$schema": "./apisnaprc.schema.json",
|
|
322
360
|
"port": "3000",
|
|
323
361
|
"slow": "300",
|
|
324
362
|
"timeout": "5000",
|
|
325
363
|
"retry": "1",
|
|
326
364
|
"concurrency": 5,
|
|
365
|
+
"openapi": "./openapi.json",
|
|
327
366
|
"body": {
|
|
328
367
|
"name": "test",
|
|
329
368
|
"email": "test@example.com"
|
|
@@ -342,13 +381,19 @@ APISnap reads the config file automatically.
|
|
|
342
381
|
"routes": [
|
|
343
382
|
{
|
|
344
383
|
"path": "/api/users",
|
|
345
|
-
"body": { "name": "John", "email": "john@example.com" }
|
|
384
|
+
"body": { "name": "John", "email": "john@example.com" },
|
|
385
|
+
"timeout": 10000
|
|
346
386
|
},
|
|
347
387
|
{
|
|
348
388
|
"path": "/api/products",
|
|
349
389
|
"body": { "title": "Widget", "price": 9.99 }
|
|
350
390
|
}
|
|
351
|
-
]
|
|
391
|
+
],
|
|
392
|
+
"envs": {
|
|
393
|
+
"staging": {
|
|
394
|
+
"baseUrl": "https://staging.example.com"
|
|
395
|
+
}
|
|
396
|
+
}
|
|
352
397
|
}
|
|
353
398
|
```
|
|
354
399
|
|
|
@@ -358,6 +403,7 @@ APISnap reads the config file automatically.
|
|
|
358
403
|
|
|
359
404
|
```bash
|
|
360
405
|
npx @umeshindu222/apisnap [options]
|
|
406
|
+
npx @umeshindu222/apisnap doctor [options]
|
|
361
407
|
```
|
|
362
408
|
|
|
363
409
|
| Option | Description | Default |
|
|
@@ -371,11 +417,28 @@ npx @umeshindu222/apisnap [options]
|
|
|
371
417
|
| `-e, --export <file>` | Save JSON report to file | — |
|
|
372
418
|
| `--html <file>` | Save HTML report to file | — |
|
|
373
419
|
| `--only <methods>` | Only test these methods e.g. `GET,POST` | — |
|
|
420
|
+
| `--filter <pattern>` | Path substring/glob filter e.g. `/api/users*` | — |
|
|
374
421
|
| `--base-url <url>` | Test a different server e.g. staging | `localhost` |
|
|
375
422
|
| `--params <json>` | Override path params as JSON | — |
|
|
423
|
+
| `--dry-run` | Print resolved endpoint plan and exit | `false` |
|
|
376
424
|
| `--fail-on-slow` | Exit code 1 if slow routes found | `false` |
|
|
377
425
|
| `--concurrency <n>` | Concurrent requests to run | `1` |
|
|
378
426
|
| `--body <json>` | Default JSON body for POST/PUT/PATCH | — |
|
|
427
|
+
| `--auth-flow` | Execute configured authFlow login before tests | `false` |
|
|
428
|
+
| `--session` | Capture/replay cookies from responses | `false` |
|
|
429
|
+
| `--save-baseline <file>` | Save run as baseline JSON | — |
|
|
430
|
+
| `--diff <file>` | Compare against baseline and show regressions | — |
|
|
431
|
+
| `--openapi <file>` | Discover routes from OpenAPI JSON | — |
|
|
432
|
+
| `--ci` | CI-friendly JSON output and strict exit logic | `false` |
|
|
433
|
+
| `--env <name>` | Load environment profile from config | — |
|
|
434
|
+
|
|
435
|
+
Doctor options:
|
|
436
|
+
|
|
437
|
+
| Option | Description | Default |
|
|
438
|
+
|--------|-------------|---------|
|
|
439
|
+
| `doctor` | Diagnose config, server reachability, and middleware wiring | — |
|
|
440
|
+
| `doctor -p, --port <n>` | Port to diagnose | config/`3000` |
|
|
441
|
+
| `doctor --env <name>` | Diagnose a specific config environment | — |
|
|
379
442
|
|
|
380
443
|
---
|
|
381
444
|
|
|
@@ -436,6 +499,31 @@ npx @umeshindu222/apisnap --export report
|
|
|
436
499
|
npx @umeshindu222/apisnap --retry 3
|
|
437
500
|
```
|
|
438
501
|
|
|
502
|
+
### Preview routes only (no HTTP calls)
|
|
503
|
+
```bash
|
|
504
|
+
npx @umeshindu222/apisnap --dry-run --filter "/api/users*"
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Diff against baseline and fail on regressions
|
|
508
|
+
```bash
|
|
509
|
+
npx @umeshindu222/apisnap --diff baseline.json
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Save a baseline for future comparisons
|
|
513
|
+
```bash
|
|
514
|
+
npx @umeshindu222/apisnap --save-baseline baseline.json
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Discover from OpenAPI instead of live discovery
|
|
518
|
+
```bash
|
|
519
|
+
npx @umeshindu222/apisnap --openapi ./openapi.json
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Run setup diagnostics
|
|
523
|
+
```bash
|
|
524
|
+
npx @umeshindu222/apisnap doctor -p 3000
|
|
525
|
+
```
|
|
526
|
+
|
|
439
527
|
### CI/CD — fail the pipeline if any endpoint is broken
|
|
440
528
|
```bash
|
|
441
529
|
npx @umeshindu222/apisnap --export ci-report
|
|
@@ -460,7 +548,7 @@ npx @umeshindu222/apisnap \
|
|
|
460
548
|
## Sample Output
|
|
461
549
|
|
|
462
550
|
```
|
|
463
|
-
📸 APISnap v1.
|
|
551
|
+
📸 APISnap v1.2.3
|
|
464
552
|
Target: http://localhost:3000
|
|
465
553
|
Slow: >200ms
|
|
466
554
|
Timeout: 5000ms
|
|
@@ -481,6 +569,9 @@ npx @umeshindu222/apisnap \
|
|
|
481
569
|
❌ Failed: 1
|
|
482
570
|
⚠️ Slow: 1 (>200ms)
|
|
483
571
|
⏱ Avg: 95ms
|
|
572
|
+
📈 p50: 12ms
|
|
573
|
+
📈 p95: 543ms
|
|
574
|
+
📈 p99: 543ms
|
|
484
575
|
🕐 Total: 573ms
|
|
485
576
|
|
|
486
577
|
⚠️ Some endpoints are unhealthy!
|
|
@@ -493,7 +584,7 @@ npx @umeshindu222/apisnap \
|
|
|
493
584
|
```json
|
|
494
585
|
{
|
|
495
586
|
"tool": "APISnap",
|
|
496
|
-
"version": "1.
|
|
587
|
+
"version": "1.2.3",
|
|
497
588
|
"generatedAt": "2026-03-08T10:00:00.000Z",
|
|
498
589
|
"config": {
|
|
499
590
|
"port": "3000",
|
|
@@ -506,6 +597,9 @@ npx @umeshindu222/apisnap \
|
|
|
506
597
|
"failed": 1,
|
|
507
598
|
"slow": 1,
|
|
508
599
|
"avgDuration": 95,
|
|
600
|
+
"p50Duration": 12,
|
|
601
|
+
"p95Duration": 543,
|
|
602
|
+
"p99Duration": 543,
|
|
509
603
|
"totalDuration": 573
|
|
510
604
|
},
|
|
511
605
|
"results": [
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://umeshindu222.github.io/apisnap/apisnaprc.schema.json",
|
|
4
|
+
"title": "APISnap Configuration",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": true,
|
|
7
|
+
"properties": {
|
|
8
|
+
"port": {
|
|
9
|
+
"type": ["string", "number"],
|
|
10
|
+
"default": 3000
|
|
11
|
+
},
|
|
12
|
+
"slow": {
|
|
13
|
+
"type": ["string", "number"],
|
|
14
|
+
"default": 200
|
|
15
|
+
},
|
|
16
|
+
"timeout": {
|
|
17
|
+
"type": ["string", "number"],
|
|
18
|
+
"default": 5000
|
|
19
|
+
},
|
|
20
|
+
"retry": {
|
|
21
|
+
"type": ["string", "number"],
|
|
22
|
+
"default": 0
|
|
23
|
+
},
|
|
24
|
+
"concurrency": {
|
|
25
|
+
"type": ["string", "number"],
|
|
26
|
+
"default": 1
|
|
27
|
+
},
|
|
28
|
+
"baseUrl": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"openapi": {
|
|
32
|
+
"type": ["string", "boolean"],
|
|
33
|
+
"description": "Path to OpenAPI JSON file used for discovery"
|
|
34
|
+
},
|
|
35
|
+
"cookie": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"headers": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"items": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"params": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"additionalProperties": {
|
|
47
|
+
"type": ["string", "number", "boolean"]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"body": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": true
|
|
53
|
+
},
|
|
54
|
+
"skip": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"authFlow": {
|
|
61
|
+
"$ref": "#/definitions/AuthFlow"
|
|
62
|
+
},
|
|
63
|
+
"routes": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": {
|
|
66
|
+
"$ref": "#/definitions/RouteConfig"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"envs": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"additionalProperties": {
|
|
72
|
+
"type": "object"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"definitions": {
|
|
77
|
+
"AuthFlow": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"required": ["url", "body", "tokenPath"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"url": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
},
|
|
84
|
+
"body": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"additionalProperties": true
|
|
87
|
+
},
|
|
88
|
+
"tokenPath": {
|
|
89
|
+
"type": "string"
|
|
90
|
+
},
|
|
91
|
+
"headerName": {
|
|
92
|
+
"type": "string"
|
|
93
|
+
},
|
|
94
|
+
"prefix": {
|
|
95
|
+
"type": "string"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"RouteConfig": {
|
|
100
|
+
"type": "object",
|
|
101
|
+
"required": ["path"],
|
|
102
|
+
"properties": {
|
|
103
|
+
"path": {
|
|
104
|
+
"type": "string"
|
|
105
|
+
},
|
|
106
|
+
"body": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"additionalProperties": true
|
|
109
|
+
},
|
|
110
|
+
"headers": {
|
|
111
|
+
"type": "array",
|
|
112
|
+
"items": {
|
|
113
|
+
"type": "string"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"auth": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"enum": ["none"]
|
|
119
|
+
},
|
|
120
|
+
"timeout": {
|
|
121
|
+
"type": "number",
|
|
122
|
+
"minimum": 1
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"additionalProperties": true
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|