Skip to content

Commit b06f4d5

Browse files
authored
Merge pull request #3 from cube-root/mocks
Mocks
2 parents 130b6b0 + 5bd6133 commit b06f4d5

12 files changed

Lines changed: 1076 additions & 82 deletions

File tree

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ That's it! Your local server running on port 3000 is now accessible from the int
2020
- **Request Inspector** - Built-in web UI to monitor all proxied requests and responses in real-time
2121
- **API Composer** - Postman-like request builder inside the inspector to craft and send HTTP requests
2222
- **cURL Export** - Generate copy-ready cURL commands from any captured request
23+
- **Mock Mode** - Define mock responses for API paths without a running backend, with a web UI to manage mocks
2324
- **Token Protection** - Secure your tunnels with authentication tokens
2425
- **Self-Hostable** - Run your own ProxyHub server
2526
- **Session Timeouts** - Configurable session duration limits
@@ -74,6 +75,31 @@ Inspector features:
7475
- **cURL export** — expand the cURL section on any request detail page to get a ready-to-copy command
7576
- Light/dark theme
7677

78+
### Mock Mode
79+
80+
Define mock API responses without needing a real backend server. Mock mode includes a web UI for managing mocks and supports exact, prefix, and regex path matching.
81+
82+
```bash
83+
# Pure mock mode (no local server needed)
84+
proxyhub --mock
85+
86+
# Hybrid mode (mocked paths return mock data, others proxy to localhost)
87+
proxyhub --mock -p 3000
88+
89+
# Inspector automatically enables mock mode
90+
proxyhub -p 3000 --inspect
91+
```
92+
93+
Once running, open the Mock Manager URL shown in the terminal (e.g., `http://localhost:3001/mocks`) to create and manage mocks.
94+
95+
Mock features:
96+
- **Pure mock mode** — no local server required, define all responses via the UI
97+
- **Hybrid mode** — combine mocks with a real backend; mocked paths return mock data, non-mocked paths proxy normally
98+
- **Path matching** — exact, prefix, or regex matching with configurable priority
99+
- **Response customization** — set status codes, headers, body, and response delay
100+
- **Inspector integration** — mocked requests appear in the inspector with a `MOCK` badge
101+
- Enable/disable individual mocks without deleting them
102+
77103
### Token Protection
78104

79105
Secure your tunnel so only requests with the correct token can access it:
@@ -96,14 +122,17 @@ curl -H "X-Proxy-Token: mysecrettoken" https://your-tunnel.proxyhub.cloud/
96122

97123
| Option | Description |
98124
|--------|-------------|
99-
| `-p, --port <port>` | Port number to proxy (required) |
125+
| `-p, --port <port>` | Port number to proxy |
126+
| `-m, --mock` | Enable mock mode |
100127
| `-t, --token <token>` | Token for tunnel protection |
101128
| `-i, --inspect` | Enable request inspector UI |
102129
| `--inspect-port <port>` | Port for inspector UI (default: port + 1000) |
103130
| `-d, --debug` | Enable debug mode |
104131
| `-V, --version` | Output version number |
105132
| `-h, --help` | Display help |
106133

134+
Either `--port` or `--mock` is required. Using `--inspect` automatically enables mock mode.
135+
107136
## Self-Hosting
108137

109138
### Docker (Recommended)

packages/client/README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,31 @@ Inspector features:
5959
- **cURL export** — expand the cURL section on any request detail page to get a ready-to-copy command
6060
- Light/dark theme
6161

62+
### Mock Mode
63+
64+
Define mock API responses without needing a real backend server. Mock mode includes a web UI for managing mocks and supports exact, prefix, and regex path matching.
65+
66+
```bash
67+
# Pure mock mode (no local server needed)
68+
proxyhub --mock
69+
70+
# Hybrid mode (mocked paths return mock data, others proxy to localhost)
71+
proxyhub --mock -p 3000
72+
73+
# Inspector automatically enables mock mode
74+
proxyhub -p 3000 --inspect
75+
```
76+
77+
Once running, open the Mock Manager URL shown in the terminal (e.g., `http://localhost:3001/mocks`) to create and manage mocks.
78+
79+
Mock features:
80+
- **Pure mock mode** — no local server required, define all responses via the UI
81+
- **Hybrid mode** — combine mocks with a real backend; mocked paths return mock data, non-mocked paths proxy normally
82+
- **Path matching** — exact, prefix, or regex matching with configurable priority
83+
- **Response customization** — set status codes, headers, body, and response delay
84+
- **Inspector integration** — mocked requests appear in the inspector with a `MOCK` badge
85+
- Enable/disable individual mocks without deleting them
86+
6287
### Token Protection
6388

6489
Secure your tunnel so only requests with the correct token can access it:
@@ -83,14 +108,17 @@ proxyhub -p 3000 --debug
83108

84109
| Option | Description |
85110
|--------|-------------|
86-
| `-p, --port <port>` | Port number to proxy (required) |
111+
| `-p, --port <port>` | Port number to proxy |
112+
| `-m, --mock` | Enable mock mode |
87113
| `-t, --token <token>` | Token for tunnel protection |
88114
| `-i, --inspect` | Enable request inspector UI |
89115
| `--inspect-port <port>` | Port for inspector UI (default: port + 1000) |
90116
| `-d, --debug` | Enable debug mode |
91117
| `-V, --version` | Output version number |
92118
| `-h, --help` | Display help |
93119

120+
Either `--port` or `--mock` is required. Using `--inspect` automatically enables mock mode.
121+
94122
## Self-Hosted Server
95123

96124
Connect to your own ProxyHub server using environment variables:

packages/client/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
"api",
2424
"testing"
2525
],
26-
"author": "",
26+
"author": "Abhijith V",
2727
"license": "MIT",
28+
"files": [
29+
"dist/**/*.js",
30+
"dist/**/*.d.ts"
31+
],
2832
"homepage": "https://proxyhub.app",
2933
"repository": {
3034
"type": "git",

packages/client/src/@types/index.d.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
declare global {
22
interface ClientInitializationOptions {
3-
port: number;
3+
port?: number;
44
debug?: boolean;
55
token?: string;
66
inspect?: boolean;
77
inspectPort?: number;
8+
mock?: boolean;
89
}
910

1011
interface TunnelRequestArgument {
@@ -88,6 +89,47 @@ declare global {
8889
avg_duration_ms: number | null;
8990
}
9091

92+
interface MockDefinition {
93+
id: string;
94+
method: string;
95+
path: string;
96+
path_type: 'exact' | 'prefix' | 'regex';
97+
status_code: number;
98+
headers: string;
99+
body: string | null;
100+
delay_ms: number;
101+
priority: number;
102+
enabled: number;
103+
description: string | null;
104+
created_at: string;
105+
updated_at: string;
106+
}
107+
108+
interface MockInsert {
109+
method?: string;
110+
path: string;
111+
path_type?: string;
112+
status_code?: number;
113+
headers?: string;
114+
body?: string;
115+
delay_ms?: number;
116+
priority?: number;
117+
description?: string;
118+
}
119+
120+
interface MockUpdate {
121+
method?: string;
122+
path?: string;
123+
path_type?: string;
124+
status_code?: number;
125+
headers?: string;
126+
body?: string;
127+
delay_ms?: number;
128+
priority?: number;
129+
enabled?: number;
130+
description?: string;
131+
}
132+
91133
}
92134

93135
export {};

packages/client/src/index.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,51 @@ program
2323
.name('ProxyHub')
2424
.description("Test your API's with ease - Tunnel localhost to the internet")
2525
.version(version)
26-
.requiredOption('-p, --port <port>', 'Port number for proxying', portNumberCustomValidationForCommander)
26+
.option('-p, --port <port>', 'Port number for proxying', portNumberCustomValidationForCommander)
2727
.option('-d, --debug', 'Enable debug mode', false)
2828
.option('-t, --token <token>', 'Token for tunnel protection')
2929
.option('-i, --inspect', 'Enable request inspector', false)
30+
.option('-m, --mock', 'Enable mock mode', false)
3031
.option('--inspect-port <port>', 'Port for inspector UI', parseInt);
3132

3233
// Parse command line arguments
3334
program.parse(process.argv);
3435

3536
// Get parsed options and check for env var fallback
36-
const parsedOpts = program.opts() as ClientInitializationOptions;
37+
const parsedOpts = program.opts() as ClientInitializationOptions & { port?: number };
3738
const options: ClientInitializationOptions = {
3839
port: parsedOpts.port,
3940
debug: parsedOpts.debug,
4041
token: parsedOpts.token || process.env.PROXYHUB_TOKEN,
4142
inspect: parsedOpts.inspect,
4243
inspectPort: parsedOpts.inspectPort,
44+
mock: parsedOpts.mock,
4345
};
4446

47+
// Validate: need either port or mock mode
48+
if (!options.port && !options.mock) {
49+
console.error(chalk.red('Error: Either --port or --mock is required.'));
50+
console.error(chalk.gray(' Use --port <port> to proxy to a local server'));
51+
console.error(chalk.gray(' Use --mock for pure mock mode (no local server needed)'));
52+
process.exit(1);
53+
}
54+
55+
// Mock and inspect are co-dependent — enabling either enables both
56+
if (options.mock || options.inspect) {
57+
options.mock = true;
58+
options.inspect = true;
59+
}
60+
4561
// Startup logging
4662
console.log('\nStarting ProxyHub Client...');
47-
console.log('Target:', chalk.cyan(`http://localhost:${options.port}`));
63+
if (options.port) {
64+
console.log('Target:', chalk.cyan(`http://localhost:${options.port}`));
65+
}
66+
if (options.mock && options.port) {
67+
console.log('Mode:', chalk.magenta('hybrid (mock + proxy)'));
68+
} else if (options.mock) {
69+
console.log('Mode:', chalk.magenta('pure mock (no local server)'));
70+
}
4871
if (options.token) {
4972
console.log('Token protection:', chalk.green('enabled'));
5073
}
@@ -61,7 +84,6 @@ socketHandler(options);
6184

6285
// Start inspector if enabled
6386
if (options.inspect) {
64-
const inspectPort = options.inspectPort || options.port + 1000;
65-
startInspector(inspectPort, options.port);
87+
const inspectPort = options.inspectPort || (options.port ? options.port + 1000 : 3001);
88+
startInspector(inspectPort, options.port, { mock: options.mock });
6689
}
67-

packages/client/src/lib/db.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ export function initDb(): void {
4040
CREATE INDEX IF NOT EXISTS idx_requests_method ON requests(method);
4141
CREATE INDEX IF NOT EXISTS idx_requests_status_code ON requests(status_code);
4242
CREATE INDEX IF NOT EXISTS idx_requests_path ON requests(path);
43+
44+
CREATE TABLE IF NOT EXISTS mocks (
45+
id TEXT PRIMARY KEY,
46+
method TEXT NOT NULL DEFAULT '*',
47+
path TEXT NOT NULL,
48+
path_type TEXT NOT NULL DEFAULT 'exact',
49+
status_code INTEGER NOT NULL DEFAULT 200,
50+
headers TEXT NOT NULL DEFAULT '{}',
51+
body TEXT,
52+
delay_ms INTEGER NOT NULL DEFAULT 0,
53+
priority INTEGER NOT NULL DEFAULT 0,
54+
enabled INTEGER NOT NULL DEFAULT 1,
55+
description TEXT,
56+
created_at TEXT NOT NULL,
57+
updated_at TEXT NOT NULL
58+
);
59+
CREATE INDEX IF NOT EXISTS idx_mocks_enabled ON mocks(enabled);
4360
`);
4461

4562
// Migrate: add response_body column if missing (existing DBs)
@@ -57,7 +74,7 @@ export function closeDb(): void {
5774
}
5875
}
5976

60-
function getDb(): Database.Database {
77+
export function getDb(): Database.Database {
6178
if (!db) throw new Error('Database not initialized. Call initDb() first.');
6279
return db;
6380
}

0 commit comments

Comments
 (0)