@testsmith/api-spector 0.0.1
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/bin/cli.js +53 -0
- package/build/icon.png +0 -0
- package/out/main/chunks/mock-server-ZB7zpXh9.js +102 -0
- package/out/main/chunks/script-runner-Ci5t2-bo.js +399 -0
- package/out/main/index.js +4003 -0
- package/out/main/mock.js +133 -0
- package/out/main/runner.js +375 -0
- package/out/preload/index.js +81 -0
- package/out/renderer/assets/index-B_l1FCkO.css +1827 -0
- package/out/renderer/assets/index-D2g8SYEA.js +48315 -0
- package/out/renderer/index.html +13 -0
- package/package.json +113 -0
- package/readme.md +121 -0
- package/resources/splash.html +110 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>api Spector</title>
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-D2g8SYEA.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B_l1FCkO.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@testsmith/api-spector",
|
|
3
|
+
"productName": "api Spector",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Local-first API testing tool — inspect, test and mock APIs",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/testsmith-io/api-spector"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/testsmith-io/api-spector/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/testsmith-io/api-spector",
|
|
14
|
+
"main": "out/main/index.js",
|
|
15
|
+
"bin": {
|
|
16
|
+
"api-spector": "bin/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"out/",
|
|
20
|
+
"bin/",
|
|
21
|
+
"resources/splash.html",
|
|
22
|
+
"build/icon.png"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "electron-vite dev",
|
|
26
|
+
"build": "electron-vite build",
|
|
27
|
+
"preview": "electron-vite preview",
|
|
28
|
+
"package": "electron-builder",
|
|
29
|
+
"runner": "node out/main/runner.js",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"test:coverage": "vitest run --coverage",
|
|
33
|
+
"lint": "eslint src",
|
|
34
|
+
"lint:fix": "eslint src --fix",
|
|
35
|
+
"build:icons": "node scripts/build-icons.mjs",
|
|
36
|
+
"prepare": "npm run build:icons && node scripts/patch-electron-name.mjs",
|
|
37
|
+
"prepublishOnly": "npm run build && npm run build:icons"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
41
|
+
"@eslint/js": "^9.39.4",
|
|
42
|
+
"@types/js-yaml": "^4.0.9",
|
|
43
|
+
"@types/jszip": "^3.4.0",
|
|
44
|
+
"@types/node": "^20.14.0",
|
|
45
|
+
"@types/react": "^18.3.3",
|
|
46
|
+
"@types/react-dom": "^18.3.0",
|
|
47
|
+
"@types/tv4": "^1.2.33",
|
|
48
|
+
"@types/uuid": "^10.0.0",
|
|
49
|
+
"@types/ws": "^8.18.1",
|
|
50
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
51
|
+
"autoprefixer": "^10.4.19",
|
|
52
|
+
"electron-builder": "^24.13.3",
|
|
53
|
+
"electron-vite": "^2.3.0",
|
|
54
|
+
"eslint": "^9.39.4",
|
|
55
|
+
"eslint-plugin-react": "^7.37.5",
|
|
56
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
57
|
+
"postcss": "^8.4.38",
|
|
58
|
+
"tailwindcss": "^3.4.4",
|
|
59
|
+
"typescript": "^5.5.2",
|
|
60
|
+
"typescript-eslint": "^8.57.1",
|
|
61
|
+
"vite": "^5.3.1",
|
|
62
|
+
"vitest": "^3.2.4"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@codemirror/lang-json": "^6.0.1",
|
|
66
|
+
"@codemirror/lang-xml": "^6.1.0",
|
|
67
|
+
"@codemirror/theme-one-dark": "^6.1.2",
|
|
68
|
+
"@faker-js/faker": "^10.3.0",
|
|
69
|
+
"@uiw/react-codemirror": "^4.23.0",
|
|
70
|
+
"ajv": "^8.17.1",
|
|
71
|
+
"dayjs": "^1.11.20",
|
|
72
|
+
"electron": "^31.0.0",
|
|
73
|
+
"immer": "^10.1.1",
|
|
74
|
+
"js-yaml": "^4.1.1",
|
|
75
|
+
"jszip": "^3.10.1",
|
|
76
|
+
"keytar": "^7.9.0",
|
|
77
|
+
"node-soap": "^1.0.0",
|
|
78
|
+
"react": "^18.3.1",
|
|
79
|
+
"react-dom": "^18.3.1",
|
|
80
|
+
"tv4": "^1.3.0",
|
|
81
|
+
"undici": "^6.19.2",
|
|
82
|
+
"uuid": "^10.0.0",
|
|
83
|
+
"ws": "^8.20.0",
|
|
84
|
+
"zustand": "^4.5.4"
|
|
85
|
+
},
|
|
86
|
+
"build": {
|
|
87
|
+
"appId": "com.apispector.app",
|
|
88
|
+
"productName": "api Spector",
|
|
89
|
+
"icon": "build/icon.png",
|
|
90
|
+
"files": [
|
|
91
|
+
"out/**/*"
|
|
92
|
+
],
|
|
93
|
+
"extraResources": [
|
|
94
|
+
{
|
|
95
|
+
"from": "resources/splash.html",
|
|
96
|
+
"to": "splash.html"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"mac": {
|
|
100
|
+
"category": "public.app-category.developer-tools"
|
|
101
|
+
},
|
|
102
|
+
"win": {
|
|
103
|
+
"target": "nsis"
|
|
104
|
+
},
|
|
105
|
+
"linux": {
|
|
106
|
+
"target": "AppImage"
|
|
107
|
+
},
|
|
108
|
+
"publish": {
|
|
109
|
+
"provider": "github",
|
|
110
|
+
"releaseType": "draft"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# api Spector
|
|
2
|
+
|
|
3
|
+
Local-first API testing tool. Inspect, test and mock APIs — secrets stay on your machine.
|
|
4
|
+
|
|
5
|
+
- GUI built with Electron + React
|
|
6
|
+
- CLI for running tests and mock servers in CI/CD pipelines
|
|
7
|
+
- Robot Framework & Playwright code generation
|
|
8
|
+
- AES-256-GCM encrypted secrets, never stored in plain text
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @testsmith/api-spector
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### GUI
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
api-spector ui
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Opens the desktop app. On first launch you'll be prompted to open or create a workspace.
|
|
25
|
+
|
|
26
|
+
### Run tests
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
api-spector run --workspace ./my-workspace.spector [options]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| Option | Description |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `--workspace <path>` | Path to `.spector` workspace file (required) |
|
|
35
|
+
| `--env <name>` | Environment name to activate |
|
|
36
|
+
| `--collection <name>` | Limit to a specific collection |
|
|
37
|
+
| `--tags <a,b>` | Comma-separated tag filter |
|
|
38
|
+
| `--output <path>` | Write results to file (`.json` or `.xml`) |
|
|
39
|
+
| `--format json\|junit` | Output format (inferred from `--output` extension) |
|
|
40
|
+
| `--verbose` | Print per-request console output and test details |
|
|
41
|
+
| `--bail` | Stop after first failure |
|
|
42
|
+
|
|
43
|
+
Exit code `0` = all passed, `1` = failures/errors.
|
|
44
|
+
|
|
45
|
+
### Start mock servers
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
api-spector mock --workspace ./my-workspace.spector [options]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Option | Description |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `--workspace <path>` | Path to `.spector` workspace file (required) |
|
|
54
|
+
| `--name <name>` | Start only the named server (repeat for multiple) |
|
|
55
|
+
|
|
56
|
+
Keeps running until `Ctrl+C`.
|
|
57
|
+
|
|
58
|
+
## Workspaces
|
|
59
|
+
|
|
60
|
+
A workspace is a `.spector` file that references your collections, environments and mock servers. Safe to commit to Git — secrets are encrypted, not stored in plain text.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
my-project/
|
|
64
|
+
├── my-workspace.spector
|
|
65
|
+
├── collections/
|
|
66
|
+
│ └── my-api.spector
|
|
67
|
+
└── environments/
|
|
68
|
+
├── dev.env.json
|
|
69
|
+
└── prod.env.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Encrypted secrets
|
|
73
|
+
|
|
74
|
+
Secret variables are encrypted with AES-256-GCM using a master password. Set `API_SPECTOR_MASTER_KEY` in your shell profile to avoid being prompted each session:
|
|
75
|
+
|
|
76
|
+
**macOS / Linux** (`~/.zshrc` or `~/.bashrc`):
|
|
77
|
+
```bash
|
|
78
|
+
export API_SPECTOR_MASTER_KEY="your-password"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Windows — PowerShell profile:**
|
|
82
|
+
```powershell
|
|
83
|
+
$env:API_SPECTOR_MASTER_KEY = "your-password"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Windows — Command Prompt (permanent):**
|
|
87
|
+
```cmd
|
|
88
|
+
setx API_SPECTOR_MASTER_KEY "your-password"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### CI/CD
|
|
92
|
+
|
|
93
|
+
Set `API_SPECTOR_MASTER_KEY` as a secret in your pipeline:
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
# GitHub Actions
|
|
97
|
+
env:
|
|
98
|
+
API_SPECTOR_MASTER_KEY: ${{ secrets.API_SPECTOR_MASTER_KEY }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If the key is not set, encrypted secrets will not be resolved and a warning will appear in the console output.
|
|
102
|
+
|
|
103
|
+
## Development
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Install dependencies
|
|
107
|
+
npm install
|
|
108
|
+
|
|
109
|
+
# Start in dev mode (hot reload)
|
|
110
|
+
npm run dev
|
|
111
|
+
|
|
112
|
+
# Build
|
|
113
|
+
npm run build
|
|
114
|
+
|
|
115
|
+
# Package as native app (macOS / Windows / Linux)
|
|
116
|
+
npm run package
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<style>
|
|
6
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
7
|
+
html, body {
|
|
8
|
+
width: 420px;
|
|
9
|
+
height: 280px;
|
|
10
|
+
background: #1e1b2e;
|
|
11
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
-webkit-app-region: drag;
|
|
18
|
+
user-select: none;
|
|
19
|
+
}
|
|
20
|
+
.ghost {
|
|
21
|
+
width: 90px;
|
|
22
|
+
height: 90px;
|
|
23
|
+
animation: float 2.4s ease-in-out infinite;
|
|
24
|
+
filter: drop-shadow(0 0 20px rgba(106, 163, 200, 0.7));
|
|
25
|
+
}
|
|
26
|
+
@keyframes float {
|
|
27
|
+
0%, 100% { transform: translateY(0px); }
|
|
28
|
+
50% { transform: translateY(-10px); }
|
|
29
|
+
}
|
|
30
|
+
.name {
|
|
31
|
+
margin-top: 18px;
|
|
32
|
+
color: #e4e3ea;
|
|
33
|
+
font-size: 26px;
|
|
34
|
+
font-weight: 300;
|
|
35
|
+
letter-spacing: 3px;
|
|
36
|
+
}
|
|
37
|
+
.name .hl {
|
|
38
|
+
color: #6aa3c8;
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
}
|
|
41
|
+
.tagline {
|
|
42
|
+
margin-top: 7px;
|
|
43
|
+
color: #615e6d;
|
|
44
|
+
font-size: 11px;
|
|
45
|
+
letter-spacing: 2.5px;
|
|
46
|
+
text-transform: uppercase;
|
|
47
|
+
}
|
|
48
|
+
.loader {
|
|
49
|
+
margin-top: 30px;
|
|
50
|
+
width: 110px;
|
|
51
|
+
height: 2px;
|
|
52
|
+
background: #2a2740;
|
|
53
|
+
border-radius: 1px;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
}
|
|
56
|
+
.loader-fill {
|
|
57
|
+
height: 100%;
|
|
58
|
+
width: 100%;
|
|
59
|
+
background: linear-gradient(90deg, #1a4e7e 0%, #6aa3c8 50%, #1a4e7e 100%);
|
|
60
|
+
background-size: 200% 100%;
|
|
61
|
+
border-radius: 1px;
|
|
62
|
+
animation: shimmer 1.5s linear infinite;
|
|
63
|
+
}
|
|
64
|
+
@keyframes shimmer {
|
|
65
|
+
0% { background-position: 200% 0; }
|
|
66
|
+
100% { background-position: -200% 0; }
|
|
67
|
+
}
|
|
68
|
+
/* Eye roll — pupils move in a circle, then rest, then repeat */
|
|
69
|
+
.pupil {
|
|
70
|
+
transform-box: fill-box;
|
|
71
|
+
transform-origin: center;
|
|
72
|
+
animation: eyeRoll 5s ease-in-out infinite;
|
|
73
|
+
}
|
|
74
|
+
.pupil-r {
|
|
75
|
+
animation-delay: 0.04s; /* tiny lag so eyes don't look robotic */
|
|
76
|
+
}
|
|
77
|
+
@keyframes eyeRoll {
|
|
78
|
+
0%, 18% { transform: translate(0px, 0px); } /* rest */
|
|
79
|
+
23% { transform: translate(-7px, -5px); } /* up-left */
|
|
80
|
+
28% { transform: translate(0px, -8px); } /* up */
|
|
81
|
+
33% { transform: translate(7px, -5px); } /* up-right */
|
|
82
|
+
38% { transform: translate(9px, 0px); } /* right */
|
|
83
|
+
43% { transform: translate(7px, 5px); } /* down-right */
|
|
84
|
+
48% { transform: translate(0px, 7px); } /* down */
|
|
85
|
+
53% { transform: translate(-7px, 5px); } /* down-left */
|
|
86
|
+
58% { transform: translate(-9px, 0px); } /* left */
|
|
87
|
+
63% { transform: translate(0px, 0px); } /* back */
|
|
88
|
+
100% { transform: translate(0px, 0px); } /* rest until next cycle */
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
91
|
+
</head>
|
|
92
|
+
<body>
|
|
93
|
+
<svg class="ghost" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
94
|
+
<rect width="512" height="512" rx="115" ry="115" fill="#1e1b2e"/>
|
|
95
|
+
<ellipse cx="256" cy="300" rx="145" ry="150" fill="#205d96" opacity="0.15"/>
|
|
96
|
+
<path d="M 130,225 C 130,95 382,95 382,225 L 382,390 Q 340,435 298,390 Q 256,435 214,390 Q 172,435 130,390 Z" fill="#205d96"/>
|
|
97
|
+
<path d="M 155,235 C 155,125 357,125 357,235 L 357,248 C 357,138 155,138 155,248 Z" fill="#6aa3c8" opacity="0.3"/>
|
|
98
|
+
<ellipse cx="198" cy="262" rx="29" ry="33" fill="white"/>
|
|
99
|
+
<ellipse cx="314" cy="262" rx="29" ry="33" fill="white"/>
|
|
100
|
+
<ellipse cx="204" cy="268" rx="16" ry="20" fill="#1e1b2e" class="pupil"/>
|
|
101
|
+
<ellipse cx="320" cy="268" rx="16" ry="20" fill="#1e1b2e" class="pupil pupil-r"/>
|
|
102
|
+
<ellipse cx="194" cy="254" rx="6" ry="7" fill="white" opacity="0.55"/>
|
|
103
|
+
<ellipse cx="310" cy="254" rx="6" ry="7" fill="white" opacity="0.55"/>
|
|
104
|
+
</svg>
|
|
105
|
+
|
|
106
|
+
<div class="name">api <span class="hl">Spector</span></div>
|
|
107
|
+
<div class="tagline">Sharp eyes on every API</div>
|
|
108
|
+
<div class="loader"><div class="loader-fill"></div></div>
|
|
109
|
+
</body>
|
|
110
|
+
</html>
|