@duckfly/proxy 1.0.4 → 1.0.5

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 CHANGED
@@ -24,6 +24,7 @@ This allows your API documentation and MCP (Model Context Protocol) servers to b
24
24
  - Continuously enriched API documentation
25
25
  - MCP server generation for AI integrations
26
26
  - Documentation aligned with real API usage
27
+ - No code changes required; just point your application to the proxy
27
28
 
28
29
  ## Quick Start
29
30
 
@@ -39,15 +40,41 @@ npm install -g @duckfly/proxy
39
40
  npx @duckfly/proxy
40
41
  ```
41
42
 
42
- After running, the CLI will ask for:
43
+ ### Interactive mode
44
+
45
+ When you run the CLI without arguments, it will guide you through the setup:
43
46
 
44
47
  | Prompt | Description | Default |
45
48
  |---|---|---|
46
- | **Token** | Your Duckfly application token | N/D |
49
+ | **Token** | Your Duckfly application token | |
47
50
  | **Proxy Port** | Port where the proxy listens | `8080` |
48
- | **Target URL** | Your backend API address | `http://localhost:3000` |
51
+ | **Target URL** | Your backend API address | App URL from token |
52
+
53
+ Configuration is saved locally in `.duckfly-proxy.json` so you don't need to enter it every time.
54
+
55
+ ### Command line mode
56
+
57
+ You can pass all options via CLI arguments. The CLI will only ask for what is missing.
58
+
59
+ ```bash
60
+ # Full command line (no prompts)
61
+ duckfly-proxy --token abc123 --port 8080 --target http://localhost:3000
62
+
63
+ # Hybrid: pass what you know, it asks the rest
64
+ duckfly-proxy --token abc123
65
+
66
+ # With npx
67
+ npx @duckfly/proxy --token abc123 --port 8080 --target http://localhost:3000
68
+ ```
69
+
70
+ All available flags:
49
71
 
50
- Configuration is saved locally in `.duckfly-proxy.json` so you don't need to re-enter it every time.
72
+ | Flag | Description |
73
+ |---|---|
74
+ | `--token <token>` | Duckfly application token |
75
+ | `--port <N>` | Proxy port (default: 8080) |
76
+ | `--target <url>` | URL to forward requests to |
77
+ | `--help` | Show help |
51
78
 
52
79
  ## How It Works
53
80
 
@@ -75,7 +102,25 @@ Configuration is saved locally in `.duckfly-proxy.json` so you don't need to re-
75
102
 
76
103
  Duckfly Proxy processes only technical and structural information such as HTTP methods, routes, headers, and payload formats.
77
104
 
78
- Request and response values are replaced with **placeholders** before being sent, ensuring no sensitive or user-specific data is transmitted.
105
+ Request and response values are replaced with **placeholders** before being sent, ensuring no sensitive or user specific data is transmitted.
106
+
107
+ ### What is sent
108
+
109
+ - HTTP methods and route paths
110
+ - Header names (values are redacted)
111
+ - Body structure and field names (values replaced with type appropriate placeholders)
112
+ - Status codes and content types
113
+
114
+ ### What is NOT sent
115
+
116
+ - Authentication tokens, passwords, or secrets
117
+ - Request/response body values
118
+ - Cookie values
119
+ - Query parameter values for sensitive fields
120
+
121
+ ## Host Alias
122
+
123
+ When your application domain (from the Duckfly token) differs from `localhost`, the proxy automatically adjusts the Host header so that observed requests are associated with the correct domain. This happens automatically; no configuration is needed.
79
124
 
80
125
  ## License
81
126
 
package/bin/cli.js CHANGED
@@ -8,42 +8,96 @@ const ApiClient = require('../src/api-client');
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
10
 
11
+ // ─── Constants ───────────────────────────────────────────────────
12
+
13
+ const DUCKFLY_API_URL = 'https://api.duckfly.dev';
14
+ const DUCKFLY_PROXY_URL = 'https://proxy.duckfly.dev';
15
+
16
+ const CONFIG_FILE = path.join(process.cwd(), '.duckfly-proxy.json');
17
+
18
+ // ─── Logo ────────────────────────────────────────────────────────
19
+
11
20
  const yellow = chalk.hex('#FFD54F');
12
21
  const gold = chalk.hex('#FFC107');
13
22
 
14
23
  const DUCKFLY_LOGO = `
15
24
  ${yellow(`
16
- @@@@@@@@@
17
- @%+-------=%@
18
- @@+-----------=@@
19
- @@=-----=##=-----@@
20
- @*------@@=#---+*%@
21
- @+------+%%+-=%*+*%@@
22
- @*---------=#%++%+++#%%@
23
- @@=-------=@%#++++++++%@
24
- @@+-------=*%%@@@@@@@
25
- @@@*-------===%@
26
- @%+---------------#@
27
- @%----------+--------#@
28
- @@@@%=------------#-------=@@
29
- @*------+*=-------%-------=@@
30
- @%--+@*+---------##-------+@
31
- @%=-=#%%#+----+%*------=+@@
32
- @@*==+%%##%%#=-----===*@@@
33
- @@#=============+*%#+=+*@@
34
- @@@%****#%%*+#@@@@%@@@
35
- @@@@%#++#@@@
25
+ @@@@@@@@@
26
+ @%+-------=%@
27
+ @@+-----------=@@
28
+ @@=-----=##=-----@@
29
+ @*------@@=#---+*%@
30
+ @+------+%%+-=%*+*%@@
31
+ @*---------=#%++%+++#%%@
32
+ @@=-------=@%#++++++++%@
33
+ @@+-------=*%%@@@@@@@
34
+ @@@*-------===%@
35
+ @%+---------------#@
36
+ @%----------+--------#@
37
+ @@@@%=------------#-------=@@
38
+ @*------+*=-------%-------=@@
39
+ @%--+@*+---------##-------+@
40
+ @%=-=#%%#+----+%*------=+@@
41
+ @@*==+%%##%%#=-----===*@@@
42
+ @@#=============+*%#+=+*@@
43
+ @@@%****#%%*+#@@@@%@@@
44
+ @@@@%#++#@@@
36
45
  `)}
37
46
  ${gold('═══════════════════════════════════════════════════════════════════════════════════════════')}
38
47
  ${chalk.bold.yellow(' 🦆 DUCKFLY PROXY v1.0.0 ')}
39
48
  ${gold('═══════════════════════════════════════════════════════════════════════════════════════════')}
40
- ${chalk.gray(' Capture and document your APIs automatically ')}
49
+ ${chalk.gray(' Observe and document your APIs automatically ')}
41
50
  ${chalk.gray(' https://duckfly.dev ')}
42
51
  ${gold('═══════════════════════════════════════════════════════════════════════════════════════════')}
43
52
  `;
44
53
 
45
- const DUCKFLY_API_URL = 'https://api.duckfly.dev';
46
- const DUCKFLY_PROXY_URL = 'https://proxy.duckfly.dev';
54
+ // ─── CLI arg parsing ─────────────────────────────────────────────
55
+
56
+ function parseArgs() {
57
+ const argv = process.argv.slice(2);
58
+ const args = {};
59
+ for (let i = 0; i < argv.length; i++) {
60
+ const arg = argv[i];
61
+ if (!arg.startsWith('--')) continue;
62
+ const key = arg.slice(2);
63
+ const next = argv[i + 1];
64
+ if (!next || next.startsWith('--')) {
65
+ args[key] = true;
66
+ } else {
67
+ args[key] = next;
68
+ i++;
69
+ }
70
+ }
71
+ return args;
72
+ }
73
+
74
+ const CLI_KEYS = ['token', 'port', 'target'];
75
+
76
+ function hasCliArgs(cliArgs) {
77
+ return CLI_KEYS.some(k => cliArgs[k] !== undefined);
78
+ }
79
+
80
+ // ─── Help ────────────────────────────────────────────────────────
81
+
82
+ function showHelp() {
83
+ console.log(chalk.bold.yellow('\n🦆 Duckfly Proxy\n'));
84
+ console.log(chalk.white('Uso: duckfly-proxy [opções]\n'));
85
+ console.log(chalk.white('Opções:'));
86
+ console.log(chalk.yellow(' --token <token> ') + chalk.gray('Token do Duckfly'));
87
+ console.log(chalk.yellow(' --port <N> ') + chalk.gray('Porta do proxy (default: 8080)'));
88
+ console.log(chalk.yellow(' --target <url> ') + chalk.gray('URL de destino para encaminhar as requisições'));
89
+ console.log(chalk.yellow(' --help ') + chalk.gray('Mostrar esta ajuda'));
90
+ console.log('');
91
+ console.log(chalk.white('Exemplos:'));
92
+ console.log(chalk.gray(' # Modo interativo completo'));
93
+ console.log(chalk.white(' duckfly-proxy\n'));
94
+ console.log(chalk.gray(' # Tudo via CLI (sem prompts)'));
95
+ console.log(chalk.white(' duckfly-proxy --token abc123 --port 8080 --target http://localhost:3000\n'));
96
+ console.log(chalk.gray(' # Híbrido (passa o que sabe, pergunta o que falta)'));
97
+ console.log(chalk.white(' duckfly-proxy --token abc123\n'));
98
+ }
99
+
100
+ // ─── State ───────────────────────────────────────────────────────
47
101
 
48
102
  let config = {
49
103
  token: null,
@@ -52,9 +106,10 @@ let config = {
52
106
  domainPackageId: null,
53
107
  proxyPort: 8080,
54
108
  targetUrl: null,
109
+ hostAlias: null,
55
110
  };
56
111
 
57
- const CONFIG_FILE = path.join(process.cwd(), '.duckfly-proxy.json');
112
+ // ─── Config persistence ──────────────────────────────────────────
58
113
 
59
114
  function loadConfig() {
60
115
  try {
@@ -64,7 +119,7 @@ function loadConfig() {
64
119
  config = { ...config, ...rest };
65
120
  return true;
66
121
  }
67
- } catch (error) {
122
+ } catch {
68
123
  console.log(chalk.yellow('⚠️ Erro ao carregar configuração salva'));
69
124
  }
70
125
  return false;
@@ -74,11 +129,13 @@ function saveConfig() {
74
129
  try {
75
130
  const { token, appName, appUrl, domainPackageId, proxyPort, targetUrl, hostAlias } = config;
76
131
  fs.writeFileSync(CONFIG_FILE, JSON.stringify({ token, appName, appUrl, domainPackageId, proxyPort, targetUrl, hostAlias }, null, 2));
77
- } catch (error) {
132
+ } catch {
78
133
  console.log(chalk.yellow('⚠️ Não foi possível salvar a configuração'));
79
134
  }
80
135
  }
81
136
 
137
+ // ─── Token validation ────────────────────────────────────────────
138
+
82
139
  async function validateToken(token) {
83
140
  const spinner = new Spinner(chalk.yellow('%s Validando token...'));
84
141
  spinner.setSpinnerString('|/-\\');
@@ -87,7 +144,6 @@ async function validateToken(token) {
87
144
  try {
88
145
  const apiClient = new ApiClient(DUCKFLY_API_URL, DUCKFLY_PROXY_URL, token);
89
146
  const result = await apiClient.validateToken();
90
-
91
147
  spinner.stop(true);
92
148
 
93
149
  if (result.valid) {
@@ -113,54 +169,55 @@ async function validateToken(token) {
113
169
  }
114
170
  }
115
171
 
116
- async function askQuestions() {
117
- if (!config.token) {
172
+ // ─── Hybrid prompts ──────────────────────────────────────────────
173
+
174
+ async function askTokenIfMissing(cliArgs) {
175
+ if (cliArgs.token) {
176
+ config.token = String(cliArgs.token).trim();
177
+ } else {
118
178
  const { token } = await inquirer.prompt([
119
179
  {
120
180
  type: 'password',
121
181
  name: 'token',
122
182
  message: chalk.yellow('🔑 Cole seu token do Duckfly:'),
123
183
  mask: '*',
124
- validate: (input) => {
125
- if (!input || input.trim().length === 0) {
126
- return 'Token não pode ser vazio';
127
- }
128
- return true;
129
- }
130
- }
184
+ validate: input => (!!input && input.trim().length > 0) || 'Token não pode ser vazio',
185
+ },
131
186
  ]);
132
-
133
- config.token = token;
134
-
135
- console.log('');
136
- const valid = await validateToken(config.token);
137
-
138
- if (!valid) {
139
- console.log(chalk.red('❌ Token inválido. Não é possível continuar.\n'));
140
- console.log(chalk.yellow('💡 Obtenha um token válido em: ') + chalk.white('https://duckfly.dev\n'));
141
- process.exit(1);
142
- }
187
+ config.token = token.trim();
143
188
  }
144
189
 
145
- const { proxyPort } = await inquirer.prompt([
146
- {
147
- type: 'input',
148
- name: 'proxyPort',
149
- message: chalk.yellow('🔌 Porta do proxy (porta que vai receber as requisições):'),
150
- default: config.proxyPort,
151
- validate: (input) => {
152
- const port = parseInt(input);
153
- if (isNaN(port) || port < 1 || port > 65535) {
154
- return 'Porta inválida (1-65535)';
155
- }
156
- return true;
157
- }
158
- }
159
- ]);
190
+ console.log('');
191
+ const valid = await validateToken(config.token);
192
+ if (!valid) {
193
+ console.log(chalk.red('❌ Token inválido. Não é possível continuar.\n'));
194
+ console.log(chalk.yellow('💡 Obtenha um token válido em: ') + chalk.white('https://duckfly.dev\n'));
195
+ process.exit(1);
196
+ }
197
+ }
160
198
 
161
- config.proxyPort = proxyPort;
199
+ async function askProxyConfig(cliArgs) {
200
+ // Port
201
+ if (cliArgs.port != null) {
202
+ config.proxyPort = parseInt(cliArgs.port, 10);
203
+ } else {
204
+ const { proxyPort } = await inquirer.prompt([
205
+ {
206
+ type: 'input',
207
+ name: 'proxyPort',
208
+ message: chalk.yellow('🔌 Porta do proxy (porta que vai receber as requisições):'),
209
+ default: config.proxyPort,
210
+ validate: input => {
211
+ const port = parseInt(input, 10);
212
+ if (Number.isNaN(port) || port < 1 || port > 65535) return 'Porta inválida (1-65535)';
213
+ return true;
214
+ },
215
+ },
216
+ ]);
217
+ config.proxyPort = proxyPort;
218
+ }
162
219
 
163
- // Alias: se o domínio do proxy não bate com o da aplicação, ativa automaticamente
220
+ // Host alias (automatic)
164
221
  config.hostAlias = null;
165
222
  if (config.appUrl) {
166
223
  try {
@@ -171,37 +228,36 @@ async function askQuestions() {
171
228
  config.hostAlias = appHost;
172
229
  console.log('');
173
230
  console.log(chalk.blue(' O domínio da aplicação (') + chalk.bold.white(appHost) + chalk.blue(') difere do proxy local.'));
174
- console.log(chalk.blue(' As requisições capturadas serão enviadas com o domínio ') + chalk.bold.white(appHost));
231
+ console.log(chalk.blue(' As requisições observadas serão enviadas com o domínio ') + chalk.bold.white(appHost));
175
232
  console.log(chalk.blue(' para que possam ser processadas corretamente pela aplicação.\n'));
176
233
  }
177
234
  } catch { }
178
235
  }
179
236
 
180
- const isWildcard = config.appUrl && config.appUrl.includes('*');
181
- const defaultTarget = isWildcard ? null : (config.appUrl || config.targetUrl);
182
-
183
- const { targetUrl } = await inquirer.prompt([
184
- {
185
- type: 'input',
186
- name: 'targetUrl',
187
- message: chalk.yellow('🎯 URL de destino (para onde encaminhar as requisições):'),
188
- default: defaultTarget,
189
- validate: (input) => {
190
- try {
191
- new URL(input);
192
- return true;
193
- } catch {
194
- return 'URL inválida (ex: http://localhost:3000)';
195
- }
196
- }
197
- }
198
- ]);
199
-
200
- config.targetUrl = targetUrl;
237
+ // Target URL
238
+ if (cliArgs.target) {
239
+ config.targetUrl = cliArgs.target;
240
+ } else {
241
+ const isWildcard = config.appUrl && config.appUrl.includes('*');
242
+ const defaultTarget = isWildcard ? null : (config.appUrl || config.targetUrl);
201
243
 
202
- return;
244
+ const { targetUrl } = await inquirer.prompt([
245
+ {
246
+ type: 'input',
247
+ name: 'targetUrl',
248
+ message: chalk.yellow('🎯 URL de destino (para onde encaminhar as requisições):'),
249
+ default: defaultTarget,
250
+ validate: input => {
251
+ try { new URL(input); return true; } catch { return 'URL inválida (ex: http://localhost:3000)'; }
252
+ },
253
+ },
254
+ ]);
255
+ config.targetUrl = targetUrl;
256
+ }
203
257
  }
204
258
 
259
+ // ─── Proxy startup ───────────────────────────────────────────────
260
+
205
261
  let proxyServer = null;
206
262
 
207
263
  async function startProxy() {
@@ -220,68 +276,73 @@ async function startProxy() {
220
276
  console.log(chalk.yellow(' Encaminhando para: ') + chalk.white(config.targetUrl));
221
277
  console.log(chalk.gray('─'.repeat(60)));
222
278
  console.log(chalk.blue('\n💡 Dica: Configure sua aplicação para apontar para ') + chalk.white(`http://localhost:${config.proxyPort}`));
223
- console.log(chalk.blue(' Todas as requisições serão capturadas e documentadas automaticamente!\n'));
279
+ console.log(chalk.blue(' Todas as requisições serão observadas e documentadas automaticamente!\n'));
224
280
  console.log(chalk.gray('Pressione Ctrl+C para parar o proxy\n'));
225
281
 
226
282
  saveConfig();
227
-
228
283
  } catch (error) {
229
284
  console.log(chalk.red('❌ Erro ao iniciar proxy: ') + chalk.gray(error.message));
230
285
  process.exit(1);
231
286
  }
232
287
  }
233
288
 
234
- async function main() {
235
- console.clear();
289
+ // ─── Main ────────────────────────────────────────────────────────
236
290
 
237
- console.log(DUCKFLY_LOGO);
291
+ async function main() {
292
+ const cliArgs = parseArgs();
238
293
 
239
- const hasConfig = loadConfig();
240
- let useExisting = false;
294
+ if (cliArgs.help) {
295
+ showHelp();
296
+ process.exit(0);
297
+ }
241
298
 
242
- if (hasConfig) {
243
- console.log(chalk.green('✅ Configuração anterior encontrada!\n'));
244
- console.log(chalk.gray('─'.repeat(60)));
245
- console.log(chalk.yellow(' App: ') + chalk.white(config.appName || 'N/A'));
246
- console.log(chalk.yellow(' Porta: ') + chalk.white(config.proxyPort));
247
- console.log(chalk.yellow(' Alvo: ') + chalk.white(config.targetUrl));
248
- console.log(chalk.gray('─'.repeat(60)) + '\n');
299
+ console.clear();
300
+ console.log(DUCKFLY_LOGO);
249
301
 
250
- const answer = await inquirer.prompt([
251
- {
252
- type: 'confirm',
253
- name: 'useExisting',
254
- message: chalk.yellow('Deseja usar a configuração salva?'),
255
- default: true
256
- }
257
- ]);
302
+ const hasCli = hasCliArgs(cliArgs);
258
303
 
259
- useExisting = answer.useExisting;
304
+ // If no CLI args, try loading saved config
305
+ if (!hasCli) {
306
+ const hasConfig = loadConfig();
260
307
 
261
- if (!useExisting) {
262
- config.token = null;
263
- config.appName = null;
264
- config.appUrl = null;
265
- config.domainPackageId = null;
266
- config.proxyPort = 8080;
267
- config.targetUrl = null;
268
- try { fs.unlinkSync(CONFIG_FILE); } catch { }
269
- }
270
- }
308
+ if (hasConfig) {
309
+ console.log(chalk.green('✅ Configuração anterior encontrada!\n'));
310
+ console.log(chalk.gray('─'.repeat(60)));
311
+ console.log(chalk.yellow(' App: ') + chalk.white(config.appName || 'N/A'));
312
+ console.log(chalk.yellow(' Porta: ') + chalk.white(config.proxyPort));
313
+ console.log(chalk.yellow(' Alvo: ') + chalk.white(config.targetUrl));
314
+ console.log(chalk.gray('─'.repeat(60)) + '\n');
271
315
 
272
- if (!useExisting) {
273
- await askQuestions();
274
- } else {
275
- console.log('');
276
- const valid = await validateToken(config.token);
316
+ const { useExisting } = await inquirer.prompt([
317
+ { type: 'confirm', name: 'useExisting', message: chalk.yellow('Deseja usar a configuração salva?'), default: true },
318
+ ]);
277
319
 
278
- if (!valid) {
279
- console.log(chalk.red('❌ Token salvo está inválido. Configurando novamente...\n'));
280
- config.token = null;
281
- await askQuestions();
320
+ if (useExisting) {
321
+ console.log('');
322
+ const valid = await validateToken(config.token);
323
+ if (!valid) {
324
+ console.log(chalk.red('❌ Token salvo está inválido. Configurando novamente...\n'));
325
+ config.token = null;
326
+ } else {
327
+ await startProxy();
328
+ return;
329
+ }
330
+ } else {
331
+ config.token = null;
332
+ config.appName = null;
333
+ config.appUrl = null;
334
+ config.domainPackageId = null;
335
+ config.proxyPort = 8080;
336
+ config.targetUrl = null;
337
+ try { fs.unlinkSync(CONFIG_FILE); } catch { }
338
+ }
282
339
  }
283
340
  }
284
341
 
342
+ // Fresh setup (interactive or CLI args)
343
+ await askTokenIfMissing(cliArgs);
344
+ await askProxyConfig(cliArgs);
345
+ saveConfig();
285
346
  await startProxy();
286
347
  }
287
348
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckfly/proxy",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Duckfly Proxy observes real API usage to continuously enrich and generate API documentation and MCP servers on Duckfly.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "duckfly",
21
21
  "http",
22
22
  "request",
23
- "capture"
23
+ "observe"
24
24
  ],
25
25
  "author": "Duckfly",
26
26
  "license": "MIT",
@@ -45,15 +45,28 @@ class ProxyServer {
45
45
  });
46
46
 
47
47
  this.proxy.on('proxyRes', (proxyRes, req, res) => {
48
+ const MAX_CAPTURE = 10 * 1024 * 1024; // 10MB
49
+ const contentType = (proxyRes.headers['content-type'] || '').toLowerCase();
50
+ const binaryTypes = ['image/', 'video/', 'audio/', 'application/octet-stream', 'application/pdf', 'application/zip'];
51
+ const skipBody = binaryTypes.some(t => contentType.includes(t));
52
+
48
53
  let bodyChunks = [];
54
+ let bodySize = 0;
55
+ let overflow = false;
49
56
 
50
57
  proxyRes.on('data', (chunk) => {
51
- bodyChunks.push(chunk);
58
+ bodySize += chunk.length;
59
+ if (!skipBody && !overflow) {
60
+ if (bodySize <= MAX_CAPTURE) {
61
+ bodyChunks.push(chunk);
62
+ } else {
63
+ overflow = true;
64
+ bodyChunks = [];
65
+ }
66
+ }
52
67
  });
53
68
 
54
69
  proxyRes.on('end', () => {
55
- const responseBody = Buffer.concat(bodyChunks);
56
-
57
70
  const statusColor = proxyRes.statusCode >= 400 ? chalk.red :
58
71
  proxyRes.statusCode >= 300 ? chalk.yellow :
59
72
  chalk.green;
@@ -62,9 +75,18 @@ class ProxyServer {
62
75
  chalk.blue('←'),
63
76
  statusColor(proxyRes.statusCode),
64
77
  chalk.gray(req.url),
65
- chalk.dim(`${responseBody.length} bytes`)
78
+ chalk.dim(`${bodySize} bytes`)
66
79
  );
67
80
 
81
+ let responseBody;
82
+ if (skipBody) {
83
+ responseBody = Buffer.from(`[Binary content: ${contentType}, ${bodySize} bytes]`);
84
+ } else if (overflow) {
85
+ responseBody = Buffer.from(`[Body too large: ${bodySize} bytes]`);
86
+ } else {
87
+ responseBody = Buffer.concat(bodyChunks);
88
+ }
89
+
68
90
  this.captureResponse(req, proxyRes, responseBody);
69
91
  });
70
92
  });
@@ -105,7 +127,7 @@ class ProxyServer {
105
127
  }
106
128
  };
107
129
  } catch (error) {
108
- console.log(chalk.yellow('⚠'), chalk.gray('Erro ao capturar requisição:'), error.message);
130
+ console.log(chalk.yellow('⚠'), chalk.gray('Erro ao observar requisição:'), error.message);
109
131
  }
110
132
  }
111
133
 
@@ -147,7 +169,7 @@ class ProxyServer {
147
169
  this.stats.captured++;
148
170
 
149
171
  } catch (error) {
150
- console.log(chalk.yellow('⚠'), chalk.gray('Erro ao capturar resposta:'), error.message);
172
+ console.log(chalk.yellow('⚠'), chalk.gray('Erro ao observar resposta:'), error.message);
151
173
  }
152
174
  }
153
175
 
@@ -403,7 +425,7 @@ class ProxyServer {
403
425
  process.stdout.write('\r' + chalk.bold.white('📊 Estatísticas:') + '\x1b[K\n');
404
426
  process.stdout.write('\r' + chalk.yellow(' Uptime: ') + chalk.white(`${hours}h ${minutes}m ${seconds}s`) + '\x1b[K\n');
405
427
  process.stdout.write('\r' + chalk.yellow(' Total: ') + chalk.white(this.stats.totalRequests) + '\x1b[K\n');
406
- process.stdout.write('\r' + chalk.yellow(' Capturadas: ') + chalk.white(this.stats.captured) + '\x1b[K\n');
428
+ process.stdout.write('\r' + chalk.yellow(' Observadas: ') + chalk.white(this.stats.captured) + '\x1b[K\n');
407
429
  process.stdout.write('\r' + chalk.yellow(' Enviadas: ') + chalk.green(this.stats.sent) + '\x1b[K\n');
408
430
  process.stdout.write('\r' + chalk.yellow(' Falhas: ') + (this.stats.failed > 0 ? chalk.red(this.stats.failed) : chalk.gray(this.stats.failed)) + '\x1b[K\n');
409
431
  process.stdout.write('\r' + chalk.yellow(' Na fila: ') + chalk.yellow(this.requestQueue.getQueueSize()) + '\x1b[K\n');