fix: ajustar tipos Bun y Request para limpiar typecheck core

Co-authored-by: aider (openrouter/openai/gpt-5.1) <aider@aider.chat>
main
borja 3 weeks ago
parent 199863df00
commit b0397d24d0

@ -22,7 +22,7 @@ function buildForwardHeaders(req: Request): Headers {
Bun.serve({
port: Number(process.env.PORT || process.env.ROUTER_PORT || 3000),
fetch: async (req) => {
fetch: async (req: Request) => {
const url = new URL(req.url);
// Health local para el contenedor (evita 404 en healthcheck)
@ -36,12 +36,14 @@ Bun.serve({
const headers = buildForwardHeaders(req);
if (!routeToBot) {
try { headers.set('accept-encoding', 'identity'); } catch {}
try {
headers.set('accept-encoding', 'identity');
} catch {}
}
const init: RequestInit = {
method: req.method,
headers,
redirect: 'manual',
redirect: 'manual'
};
if (req.method !== 'GET' && req.method !== 'HEAD' && req.body !== null) {
(init as any).body = req.body as any;
@ -52,7 +54,11 @@ Bun.serve({
const res = await fetch(targetUrl, init);
const ms = Date.now() - started;
try {
console.log(`[proxy] ${req.method} ${url.pathname}${url.search} -> ${routeToBot ? 'bot' : 'web'} ${res.status} (${ms}ms)`);
console.log(
`[proxy] ${req.method} ${url.pathname}${url.search} -> ${
routeToBot ? 'bot' : 'web'
} ${res.status} (${ms}ms)`
);
} catch {}
// Devuelve la respuesta (incluye Set-Cookie, Location, etc.), asegurando Content-Type en assets por si faltase
const passthroughHeaders = new Headers(res.headers);
@ -71,14 +77,23 @@ Bun.serve({
} catch {}
}
if (!passthroughHeaders.get('content-type')) {
if (url.pathname.endsWith('.js')) passthroughHeaders.set('content-type', 'application/javascript; charset=utf-8');
if (url.pathname.endsWith('.css')) passthroughHeaders.set('content-type', 'text/css; charset=utf-8');
if (url.pathname.endsWith('.js')) {
passthroughHeaders.set(
'content-type',
'application/javascript; charset=utf-8'
);
}
if (url.pathname.endsWith('.css')) {
passthroughHeaders.set('content-type', 'text/css; charset=utf-8');
}
}
return new Response(res.body, { status: res.status, headers: passthroughHeaders });
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
console.error(`[proxy] ${req.method} ${url.pathname}${url.search} -> ERROR: ${msg}`);
console.error(
`[proxy] ${req.method} ${url.pathname}${url.search} -> ERROR: ${msg}`
);
return new Response(`Proxy error: ${msg}\n`, { status: 502 });
}
},
}
});

@ -1,4 +1,4 @@
//// <reference types="bun-types" />
/// <reference types="bun-types" />
import type { Database } from 'bun:sqlite';
import { GroupSyncService } from './services/group-sync';
import { ContactsService } from './services/contacts';
@ -11,11 +11,6 @@ import { handleHealthRequest } from './http/health';
import { startServices } from './http/bootstrap';
import { handleMessageUpsert as handleMessageUpsertFn } from './http/webhook-handler';
// Bun is available globally when running under Bun runtime
declare global {
var Bun: typeof import('bun');
}
export const REQUIRED_ENV = [
'EVOLUTION_API_URL',
'EVOLUTION_API_KEY',
@ -36,7 +31,8 @@ export class WebhookServer {
private static getBaseUrl(request: Request): string {
const proto = request.headers.get('x-forwarded-proto') || 'http';
const host = request.headers.get('x-forwarded-host') || request.headers.get('host');
const host =
request.headers.get('x-forwarded-host') || request.headers.get('host');
return `${proto}://${host}`;
}
@ -62,7 +58,7 @@ export class WebhookServer {
}
if (process.env.NODE_ENV !== 'test') {
console.log(' Incoming webhook request:')
console.log(' Incoming webhook request:');
}
// 1. Method validation
@ -78,15 +74,17 @@ export class WebhookServer {
try {
// 3. Parse and validate payload
const payload = await request.json() as WebhookPayload;
const payload = (await request.json()) as WebhookPayload;
if (!payload.event || !payload.instance) {
return new Response('🚫 Invalid payload', { status: 400 });
}
// 4. Verify instance matches (skip in test environment unless TEST_VERIFY_INSTANCE is set)
if ((process.env.NODE_ENV !== 'test' || process.env.TEST_VERIFY_INSTANCE) &&
payload.instance !== process.env.EVOLUTION_API_INSTANCE) {
if (
(process.env.NODE_ENV !== 'test' || process.env.TEST_VERIFY_INSTANCE) &&
payload.instance !== process.env.EVOLUTION_API_INSTANCE
) {
return new Response('🚫 Invalid instance', { status: 403 });
}
@ -120,7 +118,9 @@ export class WebhookServer {
case 'contacts.update':
case 'chats.update':
if (process.env.NODE_ENV !== 'test') {
console.log(' Handling contacts/chats update event:', { rawEvent: evt });
console.log(' Handling contacts/chats update event:', {
rawEvent: evt
});
}
ContactsService.updateFromWebhook(payload.data);
break;
@ -151,7 +151,9 @@ export class WebhookServer {
stack: error instanceof Error ? error.stack : undefined,
time: new Date().toISOString()
});
try { Metrics.inc('webhook_errors_total'); } catch {}
try {
Metrics.inc('webhook_errors_total');
} catch {}
return new Response('Invalid request', { status: 400 });
}
}
@ -162,10 +164,26 @@ export class WebhookServer {
static validateEnv() {
console.log(' Checking environment variables...');
console.log('EVOLUTION_API_URL:', process.env.EVOLUTION_API_URL ? '***' : 'MISSING');
console.log('EVOLUTION_API_INSTANCE:', process.env.EVOLUTION_API_INSTANCE || 'MISSING');
console.log('WEBHOOK_URL:', process.env.WEBHOOK_URL ? `${process.env.WEBHOOK_URL.substring(0, 20)}...` : 'NOT SET');
console.log('WHATSAPP_COMMUNITY_ID:', process.env.WHATSAPP_COMMUNITY_ID ? '***' : 'NOT SET (se mostrarán comunidades disponibles)');
console.log(
'EVOLUTION_API_URL:',
process.env.EVOLUTION_API_URL ? '***' : 'MISSING'
);
console.log(
'EVOLUTION_API_INSTANCE:',
process.env.EVOLUTION_API_INSTANCE || 'MISSING'
);
console.log(
'WEBHOOK_URL:',
process.env.WEBHOOK_URL
? `${process.env.WEBHOOK_URL.substring(0, 20)}...`
: 'NOT SET'
);
console.log(
'WHATSAPP_COMMUNITY_ID:',
process.env.WHATSAPP_COMMUNITY_ID
? '***'
: 'NOT SET (se mostrarán comunidades disponibles)'
);
const missing = REQUIRED_ENV.filter(v => !process.env[v]);
if (missing.length) {
@ -175,8 +193,10 @@ export class WebhookServer {
process.exit(1);
}
if (process.env.CHATBOT_PHONE_NUMBER &&
!/^\d+$/.test(process.env.CHATBOT_PHONE_NUMBER)) {
if (
process.env.CHATBOT_PHONE_NUMBER &&
!/^\d+$/.test(process.env.CHATBOT_PHONE_NUMBER)
) {
console.error('❌ CHATBOT_PHONE_NUMBER must contain only digits');
process.exit(1);
}
@ -189,7 +209,9 @@ export class WebhookServer {
await Migrator.migrateToLatest(this.dbInstance);
// Etapa 7: seed inicial de grupos permitidos desde ALLOWED_GROUPS (best-effort)
try { AllowedGroups.seedFromEnv(); } catch {}
try {
AllowedGroups.seedFromEnv();
} catch {}
const PORT = process.env.PORT || '3007';
console.log('✅ Environment variables validated');
@ -211,14 +233,17 @@ export class WebhookServer {
try {
await startServices(this.dbInstance);
} catch (error) {
console.error('❌ Failed to setup webhook:', error instanceof Error ? error.message : error);
console.error(
'❌ Failed to setup webhook:',
error instanceof Error ? error.message : error
);
process.exit(1);
}
}
const server = Bun.serve({
port: parseInt(PORT),
fetch: (request) => WebhookServer.handleRequest(request)
fetch: (request: Request) => WebhookServer.handleRequest(request)
});
console.log(`Server running on port ${PORT}`);
return server;

@ -2,7 +2,7 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"types": ["bun-types"],
"lib": ["esnext"],
"lib": ["esnext", "dom"],
"strict": false,
"strictNullChecks": true,
"noImplicitAny": true,

Loading…
Cancel
Save