refactor: add pattern utils and split api.ts into modules
1. Pattern Detection Utility (src/utils/patterns.ts) - Centralize tool category patterns (domain, deposit, server, etc.) - Add memory category patterns (company, tech, role) - Add region detection (korea, japan, singapore, us) - Add tech stack detection (postgres, redis, nodejs, etc.) - Export detectToolCategories(), detectRegion(), detectTechStack() 2. API Route Modularization (src/routes/api/) - deposit.ts: /balance, /deduct with apiKeyAuth middleware - chat.ts: /test, /chat with session handling - contact.ts: Contact form with CORS middleware - metrics.ts: Circuit Breaker status endpoint 3. Updates - tools/index.ts: Use detectToolCategories from patterns.ts - api.ts: Compose sub-routers (899 → 53 lines, 94% reduction) Benefits: - Single source of truth for patterns - Better code organization - Easier maintenance and testing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
195
src/utils/patterns.ts
Normal file
195
src/utils/patterns.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Centralized pattern detection for keyword matching
|
||||
*
|
||||
* Purpose: Unified keyword matching patterns used across multiple services:
|
||||
* - Tool category detection (tools/index.ts)
|
||||
* - Memory category detection (openai-service.ts)
|
||||
* - Region/tech stack detection (server-agent.ts)
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Tool Category Patterns
|
||||
// ============================================================================
|
||||
|
||||
export const DOMAIN_PATTERNS = /도메인|네임서버|whois|dns|tld|등록|\.com|\.net|\.io|\.kr|\.org/i;
|
||||
export const DEPOSIT_PATTERNS = /입금|충전|잔액|계좌|예치금|송금|돈/i;
|
||||
export const SERVER_PATTERNS = /서버|VPS|클라우드|호스팅|인스턴스|linode|vultr/i;
|
||||
export const TROUBLESHOOT_PATTERNS = /문제|에러|오류|안[돼되]|느려|트러블|장애|버그|실패|안\s*됨/i;
|
||||
export const WEATHER_PATTERNS = /날씨|기온|비|눈|맑|흐림|더워|추워/i;
|
||||
export const SEARCH_PATTERNS = /검색|찾아|뭐야|뉴스|최신/i;
|
||||
export const REDDIT_PATTERNS = /레딧|reddit|서브레딧|subreddit/i;
|
||||
|
||||
// ============================================================================
|
||||
// Memory Category Patterns
|
||||
// ============================================================================
|
||||
|
||||
// Company/workplace patterns
|
||||
export const COMPANY_PATTERNS = /(?:에서|에)\s*(?:일해|일하고|근무|다녀)/;
|
||||
|
||||
// Tech/learning patterns
|
||||
export const TECH_LEARNING_PATTERNS = /(?:공부|개발|작업|배우)/;
|
||||
|
||||
// Role patterns
|
||||
export const ROLE_PATTERNS = /(?:개발자|엔지니어|디자이너|기획자)/;
|
||||
|
||||
// Location patterns
|
||||
export const LOCATION_PATTERNS = /(?:에서|에)\s*(?:살아|거주|있어)/;
|
||||
|
||||
// Server/infrastructure patterns (for memory)
|
||||
export const SERVER_INFRA_PATTERNS = /(?:AWS|GCP|Azure|Vultr|Linode|DigitalOcean|클라우드|가비아|카페24|서버\s*\d|트래픽|DAU|MAU|동시접속|쿠버네티스|k8s|도커|docker|컨테이너)/i;
|
||||
|
||||
// ============================================================================
|
||||
// Region Patterns (Korean/English/Japanese)
|
||||
// ============================================================================
|
||||
|
||||
export const REGION_PATTERNS = {
|
||||
korea: /한국|서울|korea|seoul|kr\b/i,
|
||||
japan: /일본|도쿄|tokyo|japan|jp\b/i,
|
||||
osaka: /오사카|osaka/i,
|
||||
singapore: /싱가포르|singapore|sg\b/i,
|
||||
us: /미국|us|america|달라스|프리몬트/i,
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// Tech Stack Patterns
|
||||
// ============================================================================
|
||||
|
||||
export const TECH_PATTERNS = {
|
||||
// Databases
|
||||
postgresql: /postgresql|postgres|postgis/i,
|
||||
mysql: /mysql|mariadb/i,
|
||||
mongodb: /mongodb|mongo/i,
|
||||
|
||||
// Cache/Messaging
|
||||
redis: /redis/i,
|
||||
memcached: /memcached/i,
|
||||
messaging: /kafka|rabbitmq/i,
|
||||
|
||||
// Runtimes
|
||||
nodejs: /node\.?js|nodejs|express/i,
|
||||
python: /python|django|flask|fastapi/i,
|
||||
java: /java|spring/i,
|
||||
go: /golang|go\s/i,
|
||||
|
||||
// Platforms
|
||||
wordpress: /wordpress/i,
|
||||
php: /laravel|php/i,
|
||||
|
||||
// Service Types
|
||||
saas: /saas|b2b|enterprise/i,
|
||||
ecommerce: /ecommerce|쇼핑몰|이커머스/i,
|
||||
game: /게임|game|minecraft|팰월드|palworld/i,
|
||||
streaming: /streaming|스트리밍|video/i,
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
// Pattern Matching Functions
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Check if text matches a given pattern
|
||||
*/
|
||||
export function matchesPattern(text: string, pattern: RegExp): boolean {
|
||||
return pattern.test(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect tool categories from message text
|
||||
* @returns Array of category names that match
|
||||
*/
|
||||
export function detectToolCategories(text: string): string[] {
|
||||
const categories: string[] = [];
|
||||
|
||||
if (DOMAIN_PATTERNS.test(text)) categories.push('domain');
|
||||
if (DEPOSIT_PATTERNS.test(text)) categories.push('deposit');
|
||||
if (SERVER_PATTERNS.test(text)) categories.push('server');
|
||||
if (TROUBLESHOOT_PATTERNS.test(text)) categories.push('troubleshoot');
|
||||
if (WEATHER_PATTERNS.test(text)) categories.push('weather');
|
||||
if (SEARCH_PATTERNS.test(text)) categories.push('search');
|
||||
if (REDDIT_PATTERNS.test(text)) categories.push('reddit');
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect memory category from message content
|
||||
* @returns Category name or null if no match
|
||||
*/
|
||||
export type MemoryCategory = 'company' | 'tech' | 'role' | 'location' | 'server' | null;
|
||||
|
||||
export function detectMemoryCategory(content: string): MemoryCategory {
|
||||
// Company/workplace
|
||||
if (COMPANY_PATTERNS.test(content)) {
|
||||
return 'company';
|
||||
}
|
||||
// Tech/learning
|
||||
if (TECH_LEARNING_PATTERNS.test(content)) {
|
||||
return 'tech';
|
||||
}
|
||||
// Role
|
||||
if (ROLE_PATTERNS.test(content)) {
|
||||
return 'role';
|
||||
}
|
||||
// Location
|
||||
if (LOCATION_PATTERNS.test(content)) {
|
||||
return 'location';
|
||||
}
|
||||
// Server/infrastructure
|
||||
if (SERVER_INFRA_PATTERNS.test(content)) {
|
||||
return 'server';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect region preference from text
|
||||
* @returns Array of region codes or undefined
|
||||
*/
|
||||
export function detectRegion(text: string): string[] | undefined {
|
||||
const lower = text.toLowerCase();
|
||||
const regions: string[] = [];
|
||||
|
||||
if (REGION_PATTERNS.korea.test(lower)) regions.push('seoul');
|
||||
if (REGION_PATTERNS.japan.test(lower)) regions.push('tokyo');
|
||||
if (REGION_PATTERNS.osaka.test(lower)) regions.push('osaka');
|
||||
if (REGION_PATTERNS.singapore.test(lower)) regions.push('singapore');
|
||||
|
||||
return regions.length > 0 ? regions : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect tech stack from text
|
||||
* @returns Array of tech stack names
|
||||
*/
|
||||
export function detectTechStack(text: string): string[] {
|
||||
const lower = text.toLowerCase();
|
||||
const stack: string[] = [];
|
||||
|
||||
// Databases
|
||||
if (TECH_PATTERNS.postgresql.test(lower)) stack.push('postgresql');
|
||||
if (TECH_PATTERNS.mysql.test(lower)) stack.push('mysql');
|
||||
if (TECH_PATTERNS.mongodb.test(lower)) stack.push('mongodb');
|
||||
|
||||
// Cache/Messaging
|
||||
if (TECH_PATTERNS.redis.test(lower)) stack.push('redis');
|
||||
if (TECH_PATTERNS.memcached.test(lower)) stack.push('memcached');
|
||||
if (TECH_PATTERNS.messaging.test(lower)) stack.push('messaging');
|
||||
|
||||
// Runtimes
|
||||
if (TECH_PATTERNS.nodejs.test(lower)) stack.push('nodejs');
|
||||
if (TECH_PATTERNS.python.test(lower)) stack.push('python');
|
||||
if (TECH_PATTERNS.java.test(lower)) stack.push('java');
|
||||
if (TECH_PATTERNS.go.test(lower)) stack.push('go');
|
||||
|
||||
// Platforms
|
||||
if (TECH_PATTERNS.wordpress.test(lower)) stack.push('wordpress');
|
||||
if (TECH_PATTERNS.php.test(lower)) stack.push('php');
|
||||
|
||||
// Service Types
|
||||
if (TECH_PATTERNS.saas.test(lower)) stack.push('saas');
|
||||
if (TECH_PATTERNS.ecommerce.test(lower)) stack.push('ecommerce');
|
||||
if (TECH_PATTERNS.game.test(lower)) stack.push('game');
|
||||
if (TECH_PATTERNS.streaming.test(lower)) stack.push('streaming');
|
||||
|
||||
return stack;
|
||||
}
|
||||
Reference in New Issue
Block a user