9.9 KiB
9.9 KiB
Route Architecture
Before Refactoring
┌─────────────────────────────────────────────────────────────┐
│ index.ts (921 lines) │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ fetch() Handler │ │
│ │ • /setup-webhook │ │
│ │ • /webhook-info │ │
│ │ • /health │ │
│ │ • /api/deposit/balance │ │
│ │ • /api/deposit/deduct │ │
│ │ • /api/test │ │
│ │ • /api/contact │ │
│ │ • /webhook (+ handleMessage + handleCallbackQuery) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ email() Handler │ │
│ │ • SMS parsing │ │
│ │ • Auto-matching │ │
│ │ • Notifications │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ scheduled() Handler │ │
│ │ • 24h expiration cleanup │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
After Refactoring
┌─────────────────────────────────────────────────────────────┐
│ index.ts (205 lines) │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ fetch() Handler (Router) │ │
│ │ • /setup-webhook ──────────┐ │ │
│ │ • /webhook-info ───────────┤ │ │
│ │ • /health ──────────────────┼──→ routes/health.ts │ │
│ │ • /api/* ───────────────────┼──→ routes/api.ts │ │
│ │ • /webhook ─────────────────┴──→ routes/webhook.ts │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ email() Handler (unchanged) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ scheduled() Handler (unchanged) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ health.ts │ │ api.ts │ │ webhook.ts │
│ (14 lines) │ │ (318 lines) │ │ (287 lines) │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ • status │ │ • balance │ │ • message │
│ • timestamp │ │ • deduct │ │ • callback │
│ │ │ • test │ │ • rate limit │
│ │ │ • contact │ │ • commands │
└──────────────┘ └──────────────┘ └──────────────┘
Request Flow Examples
1. Telegram Message
User sends message
↓
Telegram API → /webhook
↓
index.ts:fetch() → routes/webhook.ts:handleWebhook()
↓
validateWebhookRequest() (security check)
↓
handleMessage()
├─ checkRateLimit() (KV-based)
├─ getOrCreateUser() (DB)
├─ handleCommand() OR generateAIResponse()
└─ sendMessage() (Telegram API)
2. Deposit Balance Inquiry
namecheap-api → /api/deposit/balance?telegram_id=123
↓
index.ts:fetch() → routes/api.ts:handleApiRequest()
↓
X-API-Key authentication
↓
DB query (users + user_deposits)
↓
JSON response { telegram_id, balance }
3. Contact Form Submission
Web form → /api/contact (POST)
↓
index.ts:fetch() → routes/api.ts:handleApiRequest()
↓
CORS check (hosting.inouter.com)
↓
Validation (email format, message length)
↓
sendMessage() to admin (Telegram notification)
4. Health Check
Monitoring → /health (GET)
↓
index.ts:fetch() → routes/health.ts:handleHealthCheck()
↓
JSON response { status: 'ok', timestamp }
Module Dependencies
routes/webhook.ts
├── types.ts (Env, TelegramUpdate)
├── security.ts (validateWebhookRequest, checkRateLimit)
├── telegram.ts (sendMessage, sendMessageWithKeyboard, etc)
├── domain-register.ts (executeDomainRegister)
├── summary-service.ts (addToBuffer, processAndSummarize, generateAIResponse)
└── commands.ts (handleCommand)
routes/api.ts
├── types.ts (Env)
├── telegram.ts (sendMessage)
├── summary-service.ts (addToBuffer, processAndSummarize, generateAIResponse)
└── commands.ts (handleCommand)
routes/health.ts
└── (none - standalone)
index.ts
├── types.ts (Env, EmailMessage)
├── telegram.ts (sendMessage, setWebhook, getWebhookInfo)
├── services/bank-sms-parser.ts (parseBankSMS)
├── services/deposit-matcher.ts (matchPendingDeposit)
├── routes/webhook.ts (handleWebhook)
├── routes/api.ts (handleApiRequest)
└── routes/health.ts (handleHealthCheck)
Code Organization Benefits
1. Separation of Concerns
- webhook.ts: Telegram-specific logic
- api.ts: REST API endpoints
- health.ts: Monitoring
- index.ts: Routing + email + cron
2. Testability
Each route can be tested independently:
import { handleHealthCheck } from './routes/health';
const response = await handleHealthCheck();
expect(response.status).toBe(200);
3. Maintainability
- Smaller files (14-318 lines vs 921 lines)
- Clear responsibilities
- Easier to locate bugs
- Safe to modify without affecting other routes
4. Reusability
Route handlers can be:
- Imported by other modules
- Wrapped with middleware
- Tested in isolation
- Deployed independently (future: multiple workers)
Future Enhancements
Potential Middleware Layer
// src/middleware/auth.ts
export function withAuth(handler: RouteHandler) {
return async (req, env, url) => {
if (!validateAuth(req)) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
return handler(req, env, url);
};
}
// Usage in routes/api.ts
export const handleApiRequest = withAuth(async (req, env, url) => {
// ... existing logic
});
Route Registration Pattern
// src/router.ts
const routes = {
'/health': handleHealthCheck,
'/api/*': handleApiRequest,
'/webhook': handleWebhook,
};
// index.ts
const handler = routes[pathname] || notFound;
return handler(request, env, url);