@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.
@@ -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>