recker 1.0.79 → 1.0.80-next.70ea84d
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/dist/browser/browser/mini.d.ts +2 -2
- package/dist/browser/browser/recker-mini.d.ts +8 -8
- package/dist/browser/browser/recker.d.ts +11 -8
- package/dist/browser/browser/recker.js +54 -6
- package/dist/browser/core/client.d.ts +15 -10
- package/dist/browser/core/client.js +54 -38
- package/dist/browser/index.iife.min.js +129 -130
- package/dist/browser/index.min.js +129 -130
- package/dist/browser/index.mini.iife.js +5697 -636
- package/dist/browser/index.mini.iife.min.js +47 -48
- package/dist/browser/index.mini.min.js +47 -48
- package/dist/browser/index.mini.umd.js +5697 -636
- package/dist/browser/index.mini.umd.min.js +47 -48
- package/dist/browser/index.umd.min.js +129 -130
- package/dist/browser/mini.d.ts +2 -2
- package/dist/browser/plugins/proxy-rotator.d.ts +2 -2
- package/dist/browser/plugins/proxy-rotator.js +6 -28
- package/dist/browser/recker-mini.d.ts +8 -8
- package/dist/browser/recker.d.ts +11 -8
- package/dist/browser/recker.js +54 -6
- package/dist/browser/scrape/document.js +2 -2
- package/dist/browser/scrape/element.js +7 -1
- package/dist/browser/scrape/parser/nodes/html.js +1 -1
- package/dist/browser/scrape/spider.d.ts +52 -0
- package/dist/browser/scrape/spider.js +620 -38
- package/dist/browser/scrape/types.d.ts +2 -0
- package/dist/browser/search/google.d.ts +26 -1
- package/dist/browser/search/google.js +427 -45
- package/dist/browser/seo/analyzer.d.ts +1 -0
- package/dist/browser/seo/analyzer.js +144 -1
- package/dist/browser/seo/index.d.ts +1 -1
- package/dist/browser/seo/keyword-campaign-analyzer.d.ts +2 -0
- package/dist/browser/seo/keyword-campaign-analyzer.js +538 -0
- package/dist/browser/seo/keyword-campaign-seed-advanced.d.ts +17 -0
- package/dist/browser/seo/keyword-campaign-seed-advanced.js +269 -0
- package/dist/browser/seo/keyword-campaign-seed-core.d.ts +29 -0
- package/dist/browser/seo/keyword-campaign-seed-core.js +525 -0
- package/dist/browser/seo/keyword-campaign-shared.d.ts +165 -0
- package/dist/browser/seo/keyword-campaign-shared.js +59 -0
- package/dist/browser/seo/keyword-campaign.d.ts +4 -107
- package/dist/browser/seo/keyword-campaign.js +2 -380
- package/dist/browser/seo/keywords.js +5 -22
- package/dist/browser/seo/types.d.ts +19 -0
- package/dist/browser/transport/curl.d.ts +5 -1
- package/dist/browser/transport/curl.js +207 -50
- package/dist/browser/transport/undici.d.ts +4 -3
- package/dist/browser/transport/undici.js +123 -49
- package/dist/browser/types/index.d.ts +9 -3
- package/dist/browser/utils/binary-manager.js +26 -3
- package/dist/browser/utils/block-detector.d.ts +8 -0
- package/dist/browser/utils/block-detector.js +542 -7
- package/dist/cli/commands/hls-runner.js +5 -4
- package/dist/cli/commands/live-runner.js +5 -4
- package/dist/cli/commands/loadtest-runner.js +3 -2
- package/dist/cli/commands/search.d.ts +2 -0
- package/dist/cli/commands/search.js +105 -0
- package/dist/cli/commands/seo-runner.js +9 -7
- package/dist/cli/commands/seo.js +140 -1
- package/dist/cli/commands/serve.js +75 -131
- package/dist/cli/commands/server-runner.js +59 -82
- package/dist/cli/commands/spider-runner.d.ts +37 -1
- package/dist/cli/commands/spider-runner.js +134 -10
- package/dist/cli/commands/spider.d.ts +18 -1
- package/dist/cli/commands/spider.js +457 -27
- package/dist/cli/events/handlers/cli.js +30 -1
- package/dist/cli/events/handlers/tui.js +26 -0
- package/dist/cli/events/types.d.ts +27 -0
- package/dist/cli/handler.d.ts +2 -12
- package/dist/cli/handler.js +20 -15
- package/dist/cli/handlers/protocols.js +39 -12
- package/dist/cli/handlers/search.d.ts +2 -0
- package/dist/cli/handlers/search.js +171 -0
- package/dist/cli/handlers/seo-analyze.d.ts +1 -0
- package/dist/cli/handlers/seo-analyze.js +666 -0
- package/dist/cli/handlers/seo-robots.d.ts +1 -0
- package/dist/cli/handlers/seo-robots.js +76 -0
- package/dist/cli/handlers/seo-serp.d.ts +54 -0
- package/dist/cli/handlers/seo-serp.js +243 -0
- package/dist/cli/handlers/seo-sitemap.d.ts +1 -0
- package/dist/cli/handlers/seo-sitemap.js +55 -0
- package/dist/cli/handlers/seo-spider.d.ts +1 -0
- package/dist/cli/handlers/seo-spider.js +334 -0
- package/dist/cli/handlers/seo.d.ts +8 -4
- package/dist/cli/handlers/seo.js +294 -442
- package/dist/cli/handlers/spider.js +94 -17
- package/dist/cli/handlers/streaming.js +5 -1
- package/dist/cli/index.js +11 -2
- package/dist/cli/presets.d.ts +1 -1
- package/dist/cli/presets.js +15 -4
- package/dist/cli/tui/app.js +6 -1
- package/dist/cli/tui/components/rich-response.d.ts +72 -0
- package/dist/cli/tui/components/rich-response.js +117 -0
- package/dist/cli/tui/executor-commands/background.js +30 -24
- package/dist/cli/tui/executor-commands/testing.js +3 -2
- package/dist/cli/tui/hooks/useDomains.d.ts +17 -0
- package/dist/cli/tui/hooks/useHelp.js +15 -2
- package/dist/cli/tui/job-manager.d.ts +4 -4
- package/dist/cli/tui/job-manager.js +5 -1
- package/dist/cli/tui/spider-tui.d.ts +63 -0
- package/dist/cli/tui/spider-tui.js +120 -2
- package/dist/cli/types.d.ts +12 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utils/option-helpers.d.ts +10 -0
- package/dist/cli/utils/option-helpers.js +63 -0
- package/dist/cli/utils/score-color.d.ts +11 -0
- package/dist/cli/utils/score-color.js +11 -0
- package/dist/cli/utils/serp-campaign.d.ts +53 -0
- package/dist/cli/utils/serp-campaign.js +53 -0
- package/dist/cli/utils/serp-config.d.ts +26 -0
- package/dist/cli/utils/serp-config.js +125 -0
- package/dist/core/client.d.ts +15 -10
- package/dist/core/client.js +54 -38
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/cli.js +35 -34
- package/dist/mcp/client.d.ts +2 -2
- package/dist/mcp/client.js +20 -2
- package/dist/mcp/contract.d.ts +1 -1
- package/dist/mcp/profiles.js +5 -1
- package/dist/mcp/prompts/index.js +8 -4
- package/dist/mcp/resources/index.js +46 -23
- package/dist/mcp/server.js +9 -6
- package/dist/mcp/tools/protocols.js +9 -2
- package/dist/mcp/tools/registry.js +13 -3
- package/dist/mcp/tools/seo.js +427 -2
- package/dist/mcp/types.d.ts +5 -1
- package/dist/plugins/proxy-rotator.d.ts +2 -2
- package/dist/plugins/proxy-rotator.js +6 -28
- package/dist/raffel/client.d.ts +38 -0
- package/dist/raffel/client.js +282 -0
- package/dist/raffel/index.d.ts +2 -0
- package/dist/raffel/index.js +2 -0
- package/dist/raffel/types.d.ts +40 -0
- package/dist/raffel/types.js +14 -0
- package/dist/recker.d.ts +13 -7
- package/dist/recker.js +58 -6
- package/dist/scrape/document.js +2 -2
- package/dist/scrape/element.js +7 -1
- package/dist/scrape/parser/nodes/html.js +1 -1
- package/dist/scrape/spider.d.ts +52 -0
- package/dist/scrape/spider.js +620 -38
- package/dist/scrape/types.d.ts +2 -0
- package/dist/search/google.d.ts +26 -1
- package/dist/search/google.js +427 -45
- package/dist/search/index.d.ts +1 -1
- package/dist/seo/analyzer.d.ts +1 -0
- package/dist/seo/analyzer.js +144 -1
- package/dist/seo/index.d.ts +1 -1
- package/dist/seo/keyword-campaign-analyzer.d.ts +2 -0
- package/dist/seo/keyword-campaign-analyzer.js +538 -0
- package/dist/seo/keyword-campaign-seed-advanced.d.ts +17 -0
- package/dist/seo/keyword-campaign-seed-advanced.js +269 -0
- package/dist/seo/keyword-campaign-seed-core.d.ts +29 -0
- package/dist/seo/keyword-campaign-seed-core.js +525 -0
- package/dist/seo/keyword-campaign-shared.d.ts +165 -0
- package/dist/seo/keyword-campaign-shared.js +59 -0
- package/dist/seo/keyword-campaign.d.ts +4 -107
- package/dist/seo/keyword-campaign.js +2 -380
- package/dist/seo/keywords.js +5 -22
- package/dist/seo/types.d.ts +19 -0
- package/dist/template/index.d.ts +1 -1
- package/dist/template/types.d.ts +0 -2
- package/dist/testing/index.d.ts +1 -22
- package/dist/testing/index.js +1 -11
- package/dist/transport/curl.d.ts +5 -1
- package/dist/transport/curl.js +207 -50
- package/dist/transport/undici.d.ts +4 -3
- package/dist/transport/undici.js +123 -49
- package/dist/types/index.d.ts +9 -3
- package/dist/utils/binary-manager.js +26 -3
- package/dist/utils/block-detector.d.ts +8 -0
- package/dist/utils/block-detector.js +542 -7
- package/dist/version.js +1 -1
- package/package.json +12 -1
- package/dist/testing/mock-dns-server.d.ts +0 -69
- package/dist/testing/mock-dns-server.js +0 -269
- package/dist/testing/mock-ftp-server.d.ts +0 -89
- package/dist/testing/mock-ftp-server.js +0 -562
- package/dist/testing/mock-hls-server.d.ts +0 -80
- package/dist/testing/mock-hls-server.js +0 -381
- package/dist/testing/mock-http-server.d.ts +0 -124
- package/dist/testing/mock-http-server.js +0 -343
- package/dist/testing/mock-proxy-server.d.ts +0 -108
- package/dist/testing/mock-proxy-server.js +0 -615
- package/dist/testing/mock-sse-server.d.ts +0 -76
- package/dist/testing/mock-sse-server.js +0 -291
- package/dist/testing/mock-telnet-server.d.ts +0 -59
- package/dist/testing/mock-telnet-server.js +0 -274
- package/dist/testing/mock-udp-server.d.ts +0 -43
- package/dist/testing/mock-udp-server.js +0 -188
- package/dist/testing/mock-websocket-server.d.ts +0 -76
- package/dist/testing/mock-websocket-server.js +0 -334
- package/dist/testing/mock-whois-server.d.ts +0 -56
- package/dist/testing/mock-whois-server.js +0 -234
- package/dist/testing/proxy-certs.d.ts +0 -19
- package/dist/testing/proxy-certs.js +0 -208
|
@@ -42,22 +42,27 @@ export function registerServeCommand(program) {
|
|
|
42
42
|
.example('rek serve http --echo', 'Echo mode')
|
|
43
43
|
.action(async (args, cmdObj) => {
|
|
44
44
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
45
|
-
const {
|
|
45
|
+
const { createMockHttpServer } = await import('../../testing/index.js');
|
|
46
46
|
const port = options.port || 3000;
|
|
47
47
|
const host = options.host || '127.0.0.1';
|
|
48
48
|
const delay = options.delay || 0;
|
|
49
49
|
const useCors = !options['no-cors'];
|
|
50
|
-
const server = await
|
|
50
|
+
const server = await createMockHttpServer({
|
|
51
51
|
port,
|
|
52
52
|
host,
|
|
53
53
|
delay,
|
|
54
54
|
cors: useCors,
|
|
55
55
|
});
|
|
56
56
|
if (options.echo) {
|
|
57
|
-
|
|
57
|
+
const echoHandler = (req) => ({
|
|
58
58
|
status: 200,
|
|
59
59
|
body: { method: req.method, path: req.path, query: req.query, headers: req.headers, body: req.body },
|
|
60
|
-
})
|
|
60
|
+
});
|
|
61
|
+
server.get('/*', echoHandler);
|
|
62
|
+
server.post('/*', echoHandler);
|
|
63
|
+
server.put('/*', echoHandler);
|
|
64
|
+
server.patch('/*', echoHandler);
|
|
65
|
+
server.delete('/*', echoHandler);
|
|
61
66
|
}
|
|
62
67
|
console.log(colors.green(`
|
|
63
68
|
┌─────────────────────────────────────────────┐
|
|
@@ -69,8 +74,9 @@ export function registerServeCommand(program) {
|
|
|
69
74
|
├─────────────────────────────────────────────┤
|
|
70
75
|
│ Press ${colors.bold('Ctrl+C')} to stop │
|
|
71
76
|
└─────────────────────────────────────────────┘`));
|
|
72
|
-
server.
|
|
77
|
+
server.addInterceptor((req, res) => {
|
|
73
78
|
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(req.method.padEnd(7)) + req.path);
|
|
79
|
+
return res;
|
|
74
80
|
});
|
|
75
81
|
process.on('SIGINT', async () => {
|
|
76
82
|
console.log(colors.yellow('\nShutting down...'));
|
|
@@ -105,7 +111,7 @@ export function registerServeCommand(program) {
|
|
|
105
111
|
.example('rek serve webhook --status=200', 'Return 200 OK')
|
|
106
112
|
.action(async (args, cmdObj) => {
|
|
107
113
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
108
|
-
const {
|
|
114
|
+
const { createMockHttpServer } = await import('../../testing/index.js');
|
|
109
115
|
const port = options.port || 3000;
|
|
110
116
|
const host = options.host || '127.0.0.1';
|
|
111
117
|
const status = options.status || 204;
|
|
@@ -113,12 +119,13 @@ export function registerServeCommand(program) {
|
|
|
113
119
|
console.error(colors.red('Status must be 200 or 204'));
|
|
114
120
|
process.exit(1);
|
|
115
121
|
}
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
const webhookHandler = () => ({ status });
|
|
123
|
+
const server = await createMockHttpServer({ port, host });
|
|
124
|
+
server.get('/*', webhookHandler);
|
|
125
|
+
server.post('/*', webhookHandler);
|
|
126
|
+
server.put('/*', webhookHandler);
|
|
127
|
+
server.patch('/*', webhookHandler);
|
|
128
|
+
server.delete('/*', webhookHandler);
|
|
122
129
|
console.log(colors.green(`
|
|
123
130
|
┌─────────────────────────────────────────────┐
|
|
124
131
|
│ ${colors.bold('Recker Webhook Receiver')} │
|
|
@@ -133,7 +140,7 @@ export function registerServeCommand(program) {
|
|
|
133
140
|
└─────────────────────────────────────────────┘`));
|
|
134
141
|
process.on('SIGINT', async () => {
|
|
135
142
|
console.log(colors.yellow('\nShutting down...'));
|
|
136
|
-
console.log(colors.gray(`Total webhooks received: ${server.
|
|
143
|
+
console.log(colors.gray(`Total webhooks received: ${server.statistics.totalRequests}`));
|
|
137
144
|
await server.stop();
|
|
138
145
|
process.exit(0);
|
|
139
146
|
});
|
|
@@ -167,33 +174,24 @@ export function registerServeCommand(program) {
|
|
|
167
174
|
.example('rek serve ws --no-echo', 'Disable echo mode')
|
|
168
175
|
.action(async (args, cmdObj) => {
|
|
169
176
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
170
|
-
const {
|
|
177
|
+
const { createMockWebSocketServer } = await import('../../testing/index.js');
|
|
171
178
|
const port = options.port || 8080;
|
|
172
179
|
const host = options.host || '127.0.0.1';
|
|
173
|
-
const delay = options.delay || 0;
|
|
174
180
|
const echo = !options['no-echo'];
|
|
175
|
-
const server = await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
delay,
|
|
180
|
-
});
|
|
181
|
+
const server = await createMockWebSocketServer({ port, host });
|
|
182
|
+
if (!echo) {
|
|
183
|
+
server.setMessageHandler(() => undefined);
|
|
184
|
+
}
|
|
181
185
|
console.log(colors.green(`
|
|
182
186
|
┌─────────────────────────────────────────────┐
|
|
183
187
|
│ ${colors.bold('Recker Mock WebSocket Server')} │
|
|
184
188
|
├─────────────────────────────────────────────┤
|
|
185
189
|
│ URL: ${colors.cyan(server.url.padEnd(37))}│
|
|
186
190
|
│ Echo: ${colors.yellow((echo ? 'Enabled' : 'Disabled').padEnd(36))}│
|
|
187
|
-
│ Delay: ${colors.gray((delay + 'ms').padEnd(35))}
|
|
188
191
|
├─────────────────────────────────────────────┤
|
|
189
192
|
│ Press ${colors.bold('Ctrl+C')} to stop │
|
|
190
193
|
└─────────────────────────────────────────────┘`));
|
|
191
|
-
server.on('connection', (
|
|
192
|
-
server.on('message', (msg, client) => {
|
|
193
|
-
const d = msg.data.toString();
|
|
194
|
-
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(client.id) + ` ${d.slice(0, 50)}${d.length > 50 ? '...' : ''}`);
|
|
195
|
-
});
|
|
196
|
-
server.on('disconnect', (client) => console.log(colors.red(`- Disconnected: ${client.id}`)));
|
|
194
|
+
server.on('connection', (socket) => console.log(colors.green(`+ Connected: ${socket._socket?.remoteAddress ?? 'client'}`)));
|
|
197
195
|
process.on('SIGINT', async () => {
|
|
198
196
|
console.log(colors.yellow('\nShutting down...'));
|
|
199
197
|
await server.stop();
|
|
@@ -231,19 +229,15 @@ export function registerServeCommand(program) {
|
|
|
231
229
|
.example('rek serve sse --heartbeat=5000', 'Heartbeat every 5s')
|
|
232
230
|
.action(async (args, cmdObj) => {
|
|
233
231
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
234
|
-
const {
|
|
232
|
+
const { createMockSSEServer } = await import('../../testing/index.js');
|
|
235
233
|
const readline = await import('node:readline');
|
|
236
234
|
const port = options.port || 8081;
|
|
237
235
|
const host = options.host || '127.0.0.1';
|
|
238
236
|
const path = options.path || '/events';
|
|
239
237
|
const heartbeat = options.heartbeat || 0;
|
|
240
|
-
const server = await
|
|
241
|
-
port,
|
|
242
|
-
host,
|
|
243
|
-
path,
|
|
244
|
-
});
|
|
238
|
+
const server = await createMockSSEServer({ port, host, path });
|
|
245
239
|
if (heartbeat > 0)
|
|
246
|
-
server.startPeriodicEvents('heartbeat', heartbeat);
|
|
240
|
+
server.startPeriodicEvents('heartbeat', heartbeat, () => ({ data: 'heartbeat', event: 'heartbeat' }));
|
|
247
241
|
console.log(colors.green(`
|
|
248
242
|
┌─────────────────────────────────────────────┐
|
|
249
243
|
│ ${colors.bold('Recker Mock SSE Server')} │
|
|
@@ -259,8 +253,8 @@ export function registerServeCommand(program) {
|
|
|
259
253
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
260
254
|
rl.on('line', (line) => {
|
|
261
255
|
if (line.trim()) {
|
|
262
|
-
|
|
263
|
-
console.log(colors.gray(`Broadcast to ${
|
|
256
|
+
server.sendEvent({ data: line.trim() });
|
|
257
|
+
console.log(colors.gray(`Broadcast to ${server.connectionCount} client(s): ${line.trim()}`));
|
|
264
258
|
}
|
|
265
259
|
});
|
|
266
260
|
process.on('SIGINT', async () => {
|
|
@@ -315,8 +309,7 @@ export function registerServeCommand(program) {
|
|
|
315
309
|
.example('rek serve hls -Q 1080p,720p', 'Custom qualities')
|
|
316
310
|
.action(async (args, cmdObj) => {
|
|
317
311
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
318
|
-
const {
|
|
319
|
-
const http = await import('node:http');
|
|
312
|
+
const { createMockHlsServer } = await import('../../testing/index.js');
|
|
320
313
|
const port = options.port || 8082;
|
|
321
314
|
const host = options.host || '127.0.0.1';
|
|
322
315
|
const mode = options.mode || 'vod';
|
|
@@ -329,44 +322,26 @@ export function registerServeCommand(program) {
|
|
|
329
322
|
bandwidth: [5000000, 2500000, 1400000][i] || 500000,
|
|
330
323
|
resolution: ['1920x1080', '1280x720', '854x480'][i] || '640x360',
|
|
331
324
|
}));
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
325
|
+
const hlsServer = await createMockHlsServer({
|
|
326
|
+
port,
|
|
327
|
+
host,
|
|
335
328
|
mode: mode,
|
|
336
329
|
segmentCount: segments,
|
|
337
330
|
segmentDuration: duration,
|
|
338
|
-
|
|
339
|
-
variants: variants.length > 1 ? variants : undefined,
|
|
331
|
+
variants,
|
|
340
332
|
});
|
|
341
|
-
|
|
342
|
-
const url = `${baseUrl}${req.url}`;
|
|
343
|
-
try {
|
|
344
|
-
const response = await hlsServer.transport.dispatch({ url, method: req.method || 'GET' });
|
|
345
|
-
res.statusCode = response.status;
|
|
346
|
-
response.headers.forEach((value, key) => res.setHeader(key, value));
|
|
347
|
-
const body = await response.arrayBuffer();
|
|
348
|
-
res.end(Buffer.from(body));
|
|
349
|
-
}
|
|
350
|
-
catch {
|
|
351
|
-
res.statusCode = 404;
|
|
352
|
-
res.end('Not Found');
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
httpServer.listen(port, host, () => {
|
|
356
|
-
console.log(colors.green(`
|
|
333
|
+
console.log(colors.green(`
|
|
357
334
|
┌─────────────────────────────────────────────┐
|
|
358
335
|
│ ${colors.bold('Recker Mock HLS Server')} │
|
|
359
336
|
├─────────────────────────────────────────────┤
|
|
360
|
-
│ Master: ${colors.cyan(
|
|
337
|
+
│ Master: ${colors.cyan(hlsServer.masterUrl.padEnd(34))}│
|
|
361
338
|
│ Mode: ${colors.yellow(mode.padEnd(36))}│
|
|
362
339
|
│ Qualities: ${colors.cyan(qualities.join(', ').padEnd(31))}
|
|
363
340
|
├─────────────────────────────────────────────┤
|
|
364
341
|
│ Press ${colors.bold('Ctrl+C')} to stop │
|
|
365
342
|
└─────────────────────────────────────────────┘`));
|
|
366
|
-
});
|
|
367
343
|
process.on('SIGINT', async () => {
|
|
368
344
|
console.log(colors.yellow('\nShutting down...'));
|
|
369
|
-
httpServer.close();
|
|
370
345
|
await hlsServer.stop();
|
|
371
346
|
process.exit(0);
|
|
372
347
|
});
|
|
@@ -392,16 +367,13 @@ export function registerServeCommand(program) {
|
|
|
392
367
|
.example('rek serve udp', 'Start on port 9000')
|
|
393
368
|
.action(async (args, cmdObj) => {
|
|
394
369
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
395
|
-
const {
|
|
370
|
+
const { createMockUdpServer } = await import('../../testing/index.js');
|
|
396
371
|
const port = options.port || 9000;
|
|
397
372
|
const host = options.host || '127.0.0.1';
|
|
398
373
|
const echo = !options['no-echo'];
|
|
399
|
-
const server =
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
echo,
|
|
403
|
-
});
|
|
404
|
-
await server.start();
|
|
374
|
+
const server = await createMockUdpServer({ port, host });
|
|
375
|
+
if (!echo)
|
|
376
|
+
server.setMessageHandler(() => undefined);
|
|
405
377
|
console.log(colors.green(`
|
|
406
378
|
┌─────────────────────────────────────────────┐
|
|
407
379
|
│ ${colors.bold('Recker Mock UDP Server')} │
|
|
@@ -411,9 +383,9 @@ export function registerServeCommand(program) {
|
|
|
411
383
|
├─────────────────────────────────────────────┤
|
|
412
384
|
│ Press ${colors.bold('Ctrl+C')} to stop │
|
|
413
385
|
└─────────────────────────────────────────────┘`));
|
|
414
|
-
server.on('message', (
|
|
415
|
-
const d =
|
|
416
|
-
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(`${
|
|
386
|
+
server.on('message', (message, rinfo) => {
|
|
387
|
+
const d = Buffer.isBuffer(message) ? message.toString() : String(message);
|
|
388
|
+
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(`${rinfo.address}:${rinfo.port}`) + ` ${d.slice(0, 50)}${d.length > 50 ? '...' : ''}`);
|
|
417
389
|
});
|
|
418
390
|
process.on('SIGINT', async () => {
|
|
419
391
|
console.log(colors.yellow('\nShutting down...'));
|
|
@@ -445,15 +417,11 @@ export function registerServeCommand(program) {
|
|
|
445
417
|
.example('rek serve dns', 'Start on port 5353')
|
|
446
418
|
.action(async (args, cmdObj) => {
|
|
447
419
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
448
|
-
const {
|
|
420
|
+
const { createMockDnsServer } = await import('../../testing/index.js');
|
|
449
421
|
const port = options.port || 5353;
|
|
450
422
|
const host = options.host || '127.0.0.1';
|
|
451
423
|
const delay = options.delay || 0;
|
|
452
|
-
const server = await
|
|
453
|
-
port,
|
|
454
|
-
host,
|
|
455
|
-
delay,
|
|
456
|
-
});
|
|
424
|
+
const server = await createMockDnsServer({ port, host, delay });
|
|
457
425
|
console.log(colors.green(`
|
|
458
426
|
┌─────────────────────────────────────────────┐
|
|
459
427
|
│ ${colors.bold('Recker Mock DNS Server')} │
|
|
@@ -465,7 +433,7 @@ export function registerServeCommand(program) {
|
|
|
465
433
|
│ Press ${colors.bold('Ctrl+C')} to stop │
|
|
466
434
|
└─────────────────────────────────────────────┘`));
|
|
467
435
|
server.on('query', (query) => {
|
|
468
|
-
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(query.type.padEnd(6)) + ` ${query.
|
|
436
|
+
console.log(colors.gray(`${new Date().toISOString()} `) + colors.cyan(query.type.padEnd(6)) + ` ${query.name}`);
|
|
469
437
|
});
|
|
470
438
|
process.on('SIGINT', async () => {
|
|
471
439
|
console.log(colors.yellow('\nShutting down...'));
|
|
@@ -497,15 +465,11 @@ export function registerServeCommand(program) {
|
|
|
497
465
|
.example('rek serve whois', 'Start on port 4343')
|
|
498
466
|
.action(async (args, cmdObj) => {
|
|
499
467
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
500
|
-
const {
|
|
468
|
+
const { createMockWhoisServer } = await import('../../testing/index.js');
|
|
501
469
|
const port = options.port || 4343;
|
|
502
470
|
const host = options.host || '127.0.0.1';
|
|
503
471
|
const delay = options.delay || 0;
|
|
504
|
-
const server = await
|
|
505
|
-
port,
|
|
506
|
-
host,
|
|
507
|
-
delay,
|
|
508
|
-
});
|
|
472
|
+
const server = await createMockWhoisServer({ port, host, responseDelay: delay });
|
|
509
473
|
console.log(colors.green(`
|
|
510
474
|
┌─────────────────────────────────────────────┐
|
|
511
475
|
│ ${colors.bold('Recker Mock WHOIS Server')} │
|
|
@@ -550,17 +514,12 @@ export function registerServeCommand(program) {
|
|
|
550
514
|
.example('rek serve telnet', 'Start on port 2323')
|
|
551
515
|
.action(async (args, cmdObj) => {
|
|
552
516
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
553
|
-
const {
|
|
517
|
+
const { createMockTelnetServer } = await import('../../testing/index.js');
|
|
554
518
|
const port = options.port || 2323;
|
|
555
519
|
const host = options.host || '127.0.0.1';
|
|
556
520
|
const delay = options.delay || 0;
|
|
557
521
|
const echo = !options['no-echo'];
|
|
558
|
-
const server = await
|
|
559
|
-
port,
|
|
560
|
-
host,
|
|
561
|
-
echo,
|
|
562
|
-
delay,
|
|
563
|
-
});
|
|
522
|
+
const server = await createMockTelnetServer({ port, host, responseDelay: delay });
|
|
564
523
|
console.log(colors.green(`
|
|
565
524
|
┌─────────────────────────────────────────────┐
|
|
566
525
|
│ ${colors.bold('Recker Mock Telnet Server')} │
|
|
@@ -620,21 +579,14 @@ export function registerServeCommand(program) {
|
|
|
620
579
|
.example('rek serve ftp -u admin -P secret', 'Custom credentials')
|
|
621
580
|
.action(async (args, cmdObj) => {
|
|
622
581
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
623
|
-
const {
|
|
582
|
+
const { createMockFtpServer } = await import('../../testing/index.js');
|
|
624
583
|
const port = options.port || 2121;
|
|
625
584
|
const host = options.host || '127.0.0.1';
|
|
626
585
|
const username = options.username || 'user';
|
|
627
586
|
const password = options.password || 'pass';
|
|
628
587
|
const delay = options.delay || 0;
|
|
629
588
|
const anonymous = !options['no-anonymous'];
|
|
630
|
-
const server = await
|
|
631
|
-
port,
|
|
632
|
-
host,
|
|
633
|
-
username,
|
|
634
|
-
password,
|
|
635
|
-
anonymous,
|
|
636
|
-
delay,
|
|
637
|
-
});
|
|
589
|
+
const server = await createMockFtpServer({ port, host });
|
|
638
590
|
console.log(colors.green(`
|
|
639
591
|
┌─────────────────────────────────────────────┐
|
|
640
592
|
│ ${colors.bold('Recker Mock FTP Server')} │
|
|
@@ -688,17 +640,16 @@ export function registerServeCommand(program) {
|
|
|
688
640
|
.example('curl -x http://localhost:8888 https://api.github.com/users', 'Test with curl')
|
|
689
641
|
.action(async (args, cmdObj) => {
|
|
690
642
|
const options = cmdObj.opts ? cmdObj.opts() : {};
|
|
691
|
-
const {
|
|
643
|
+
const { createMockProxyServer } = await import('../../testing/index.js');
|
|
692
644
|
const port = options.port || 8888;
|
|
693
645
|
const host = options.host || '127.0.0.1';
|
|
694
646
|
const mode = options.intercept ? 'intercept' : 'forward';
|
|
695
647
|
const logPayloads = options['log-payloads'] || false;
|
|
696
648
|
const verbose = options.verbose || false;
|
|
697
|
-
const server = await
|
|
649
|
+
const server = await createMockProxyServer({
|
|
698
650
|
port,
|
|
699
651
|
host,
|
|
700
652
|
mode: mode,
|
|
701
|
-
verbose,
|
|
702
653
|
intercept: mode === 'intercept' ? { logPayloads } : undefined,
|
|
703
654
|
});
|
|
704
655
|
const modeLabel = mode === 'intercept' ? 'Intercept (MITM)' : 'Forward (Tunnel)';
|
|
@@ -717,49 +668,42 @@ export function registerServeCommand(program) {
|
|
|
717
668
|
if (mode === 'intercept') {
|
|
718
669
|
console.log(colors.yellow('\n⚠️ MITM mode active - clients must trust the proxy CA certificate'));
|
|
719
670
|
}
|
|
720
|
-
server.on('request', (
|
|
721
|
-
const method =
|
|
722
|
-
const
|
|
723
|
-
const
|
|
671
|
+
server.on('request', ({ request, response }) => {
|
|
672
|
+
const method = (request.method ?? 'GET').padEnd(7);
|
|
673
|
+
const url = request.url ?? '';
|
|
674
|
+
const isHttps = url.startsWith('https');
|
|
675
|
+
const proto = isHttps ? colors.cyan('HTTPS') : colors.gray('HTTP ');
|
|
676
|
+
const pathname = url ? (() => { try {
|
|
677
|
+
return new URL(url).pathname;
|
|
678
|
+
}
|
|
679
|
+
catch {
|
|
680
|
+
return url;
|
|
681
|
+
} })() : '';
|
|
724
682
|
console.log(colors.gray(`${new Date().toISOString()} `) +
|
|
725
683
|
colors.green(method) +
|
|
726
|
-
|
|
727
|
-
colors.cyan(
|
|
728
|
-
(
|
|
729
|
-
});
|
|
730
|
-
server.on('response', (res) => {
|
|
731
|
-
const statusColor = res.statusCode >= 500 ? colors.red :
|
|
732
|
-
res.statusCode >= 400 ? colors.yellow :
|
|
733
|
-
res.statusCode >= 300 ? colors.cyan :
|
|
734
|
-
colors.green;
|
|
735
|
-
console.log(colors.gray(`${new Date().toISOString()} `) +
|
|
736
|
-
statusColor(`← ${res.statusCode}`) +
|
|
737
|
-
colors.gray(` ${res.latency}ms`) +
|
|
738
|
-
(res.size > 0 ? colors.gray(` ${formatBytes(res.size)}`) : ''));
|
|
684
|
+
proto + ' ' +
|
|
685
|
+
colors.cyan(url.replace(/^https?:\/\/[^/]+/, '').slice(0, 40) || '/') +
|
|
686
|
+
(response?.statusCode ? ` ${colors.gray(`← ${response.statusCode}`)}` : ''));
|
|
739
687
|
});
|
|
740
688
|
server.on('error', (err) => {
|
|
741
689
|
console.log(colors.gray(`${new Date().toISOString()} `) +
|
|
742
|
-
colors.red(`✗ ${err.
|
|
743
|
-
(err.targetHost ? colors.gray(` → ${err.targetHost}:${err.targetPort}`) : ''));
|
|
690
|
+
colors.red(`✗ ${err.message ?? err}`));
|
|
744
691
|
});
|
|
745
692
|
let statsInterval;
|
|
746
693
|
if (verbose) {
|
|
747
694
|
statsInterval = setInterval(() => {
|
|
748
|
-
const stats = server.
|
|
695
|
+
const stats = server.statistics;
|
|
749
696
|
console.log(colors.gray(`\n[stats] ${stats.totalRequests} req | ` +
|
|
750
|
-
`${stats.
|
|
751
|
-
`${formatBytes(stats.bytesIn)} in | ${formatBytes(stats.bytesOut)} out | ` +
|
|
752
|
-
`${stats.avgLatency}ms avg | ${stats.requestsPerSecond} rps\n`));
|
|
697
|
+
`${formatBytes(stats.totalBytesTransferred)} transferred\n`));
|
|
753
698
|
}, 30000);
|
|
754
699
|
}
|
|
755
700
|
process.on('SIGINT', async () => {
|
|
756
701
|
console.log(colors.yellow('\nShutting down...'));
|
|
757
702
|
if (statsInterval)
|
|
758
703
|
clearInterval(statsInterval);
|
|
759
|
-
const stats = server.
|
|
704
|
+
const stats = server.statistics;
|
|
760
705
|
console.log(colors.gray(`Final stats: ${stats.totalRequests} requests | ` +
|
|
761
|
-
`${stats.
|
|
762
|
-
`${formatBytes(stats.bytesIn + stats.bytesOut)} transferred`));
|
|
706
|
+
`${formatBytes(stats.totalBytesTransferred)} transferred`));
|
|
763
707
|
await server.stop();
|
|
764
708
|
process.exit(0);
|
|
765
709
|
});
|