refactor: add KV cache, env validation, logger types, constants

- Add KV cache abstraction layer (src/services/kv-cache.ts)
- Add Zod-based env validation (src/utils/env-validation.ts)
- Improve logger types: any → unknown for type safety
- Add centralized constants file (src/constants/index.ts)
- Fix security.ts unused import

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-29 10:40:51 +09:00
parent 3a671a5707
commit 699eed1530
6 changed files with 446 additions and 10 deletions

180
src/constants/index.ts Normal file
View File

@@ -0,0 +1,180 @@
/**
* Constants for telegram-bot-workers
*
* Centralized magic strings and configuration values for better maintainability.
*
* Usage:
* import { SESSION_KEYS, MESSAGE_MARKERS, sessionKey } from './constants';
* const key = sessionKey(SESSION_KEYS.DELETE_CONFIRM, userId);
*/
/**
* Session key prefixes for KV storage
*/
export const SESSION_KEYS = {
DELETE_CONFIRM: 'delete_confirm',
SERVER_ORDER_CONFIRM: 'server_order_confirm',
SERVER_SESSION: 'server_session',
RATE_LIMIT: 'rate_limit',
NOTIFICATION: 'notification',
} as const;
/**
* Message markers for AI response processing
*
* These markers control how responses are processed:
* - DIRECT: Pass through response without AI reinterpretation
* - KEYBOARD: Indicates inline keyboard JSON data follows
* - KEYBOARD_END: Marks end of keyboard data
* - PASSTHROUGH: Return to normal conversation flow
*/
export const MESSAGE_MARKERS = {
DIRECT: '__DIRECT__',
KEYBOARD: '__KEYBOARD__',
KEYBOARD_END: '__END__',
PASSTHROUGH: '__PASSTHROUGH__',
} as const;
/**
* Keyboard types for inline buttons
*/
export const KEYBOARD_TYPES = {
DOMAIN_REGISTER: 'domain_register',
SERVER_ORDER: 'server_order',
} as const;
/**
* Callback data prefixes for inline keyboard buttons
*
* Format: prefix:action:params
* Examples:
* - domain_reg:confirm:example.com:15000
* - server_order:confirm:order_123
*/
export const CALLBACK_PREFIXES = {
DOMAIN_REGISTER_CONFIRM: 'confirm_domain_register',
DOMAIN_REGISTER_CANCEL: 'cancel_domain_register',
SERVER_ORDER_CONFIRM: 'confirm_server_order',
SERVER_ORDER_CANCEL: 'cancel_server_order',
DELETE_CONFIRM: 'confirm_delete',
DELETE_CANCEL: 'cancel_delete',
} as const;
/**
* Transaction statuses for deposit system
*/
export const TRANSACTION_STATUS = {
PENDING: 'pending',
CONFIRMED: 'confirmed',
CANCELLED: 'cancelled',
REJECTED: 'rejected',
} as const;
/**
* Transaction types for deposit system
*/
export const TRANSACTION_TYPE = {
DEPOSIT: 'deposit',
WITHDRAWAL: 'withdrawal',
REFUND: 'refund',
} as const;
/**
* Server order statuses
*/
export const SERVER_ORDER_STATUS = {
PENDING: 'pending',
PROVISIONING: 'provisioning',
ACTIVE: 'active',
SUSPENDED: 'suspended',
TERMINATED: 'terminated',
FAILED: 'failed',
} as const;
/**
* Server actions
*/
export const SERVER_ACTION = {
RECOMMEND: 'recommend',
ORDER: 'order',
START: 'start',
STOP: 'stop',
DELETE: 'delete',
LIST: 'list',
INFO: 'info',
IMAGES: 'images',
} as const;
/**
* Domain actions
*/
export const DOMAIN_ACTION = {
REGISTER: 'register',
CHECK: 'check',
WHOIS: 'whois',
LIST: 'list',
INFO: 'info',
GET_NS: 'get_ns',
SET_NS: 'set_ns',
PRICE: 'price',
CHEAPEST: 'cheapest',
} as const;
/**
* Deposit actions
*/
export const DEPOSIT_ACTION = {
BALANCE: 'balance',
ACCOUNT: 'account',
REQUEST: 'request',
HISTORY: 'history',
CANCEL: 'cancel',
PENDING: 'pending',
CONFIRM: 'confirm',
REJECT: 'reject',
} as const;
/**
* Helper to create session key with user ID
*
* @param prefix - Session key prefix (from SESSION_KEYS)
* @param userId - User ID (telegram_id or user identifier)
* @returns Formatted session key
*
* @example
* const key = sessionKey(SESSION_KEYS.DELETE_CONFIRM, '123456');
* // Returns: 'delete_confirm:123456'
*/
export function sessionKey(prefix: string, userId: string | number): string {
return `${prefix}:${userId}`;
}
/**
* Helper to parse session key
*
* @param key - Full session key
* @returns Object with prefix and userId, or null if invalid
*
* @example
* const parsed = parseSessionKey('delete_confirm:123456');
* // Returns: { prefix: 'delete_confirm', userId: '123456' }
*/
export function parseSessionKey(key: string): { prefix: string; userId: string } | null {
const parts = key.split(':');
if (parts.length !== 2) return null;
return { prefix: parts[0], userId: parts[1] };
}
/**
* Type guards for type safety
*/
export type SessionKeyPrefix = typeof SESSION_KEYS[keyof typeof SESSION_KEYS];
export type MessageMarker = typeof MESSAGE_MARKERS[keyof typeof MESSAGE_MARKERS];
export type KeyboardType = typeof KEYBOARD_TYPES[keyof typeof KEYBOARD_TYPES];
export type CallbackPrefix = typeof CALLBACK_PREFIXES[keyof typeof CALLBACK_PREFIXES];
export type TransactionStatus = typeof TRANSACTION_STATUS[keyof typeof TRANSACTION_STATUS];
export type TransactionType = typeof TRANSACTION_TYPE[keyof typeof TRANSACTION_TYPE];
export type ServerOrderStatus = typeof SERVER_ORDER_STATUS[keyof typeof SERVER_ORDER_STATUS];
export type ServerAction = typeof SERVER_ACTION[keyof typeof SERVER_ACTION];
export type DomainAction = typeof DOMAIN_ACTION[keyof typeof DOMAIN_ACTION];
export type DepositAction = typeof DEPOSIT_ACTION[keyof typeof DEPOSIT_ACTION];