UNPKG

@k-msg/core

Version:

Core types and interfaces for K-Message platform

566 lines (559 loc) 17.8 kB
/** * Standardized error handling system for K-Message Platform */ declare enum KMessageErrorCode { UNKNOWN_ERROR = "UNKNOWN_ERROR", VALIDATION_ERROR = "VALIDATION_ERROR", CONFIGURATION_ERROR = "CONFIGURATION_ERROR", PROVIDER_NOT_FOUND = "PROVIDER_NOT_FOUND", PROVIDER_NOT_AVAILABLE = "PROVIDER_NOT_AVAILABLE", PROVIDER_AUTHENTICATION_FAILED = "PROVIDER_AUTHENTICATION_FAILED", PROVIDER_CONNECTION_FAILED = "PROVIDER_CONNECTION_FAILED", PROVIDER_RATE_LIMITED = "PROVIDER_RATE_LIMITED", PROVIDER_INSUFFICIENT_BALANCE = "PROVIDER_INSUFFICIENT_BALANCE", TEMPLATE_NOT_FOUND = "TEMPLATE_NOT_FOUND", TEMPLATE_VALIDATION_FAILED = "TEMPLATE_VALIDATION_FAILED", TEMPLATE_CREATION_FAILED = "TEMPLATE_CREATION_FAILED", TEMPLATE_MODIFICATION_FAILED = "TEMPLATE_MODIFICATION_FAILED", TEMPLATE_DELETION_FAILED = "TEMPLATE_DELETION_FAILED", MESSAGE_SEND_FAILED = "MESSAGE_SEND_FAILED", MESSAGE_INVALID_PHONE_NUMBER = "MESSAGE_INVALID_PHONE_NUMBER", MESSAGE_INVALID_VARIABLES = "MESSAGE_INVALID_VARIABLES", MESSAGE_QUOTA_EXCEEDED = "MESSAGE_QUOTA_EXCEEDED", MESSAGE_RESERVATION_FAILED = "MESSAGE_RESERVATION_FAILED", MESSAGE_CANCELLATION_FAILED = "MESSAGE_CANCELLATION_FAILED", NETWORK_TIMEOUT = "NETWORK_TIMEOUT", NETWORK_CONNECTION_FAILED = "NETWORK_CONNECTION_FAILED", NETWORK_SERVICE_UNAVAILABLE = "NETWORK_SERVICE_UNAVAILABLE", API_INVALID_REQUEST = "API_INVALID_REQUEST", API_UNAUTHORIZED = "API_UNAUTHORIZED", API_FORBIDDEN = "API_FORBIDDEN", API_NOT_FOUND = "API_NOT_FOUND", API_TOO_MANY_REQUESTS = "API_TOO_MANY_REQUESTS", API_INTERNAL_SERVER_ERROR = "API_INTERNAL_SERVER_ERROR" } interface KMessageErrorContext { providerId?: string; templateCode?: string; phoneNumber?: string; messageId?: string; requestId?: string; timestamp?: Date; [key: string]: any; } declare class KMessageError extends Error { readonly code: KMessageErrorCode; readonly context: KMessageErrorContext; readonly retryable: boolean; readonly statusCode?: number; readonly cause?: Error; constructor(code: KMessageErrorCode, message: string, context?: KMessageErrorContext, options?: { retryable?: boolean; statusCode?: number; cause?: Error; }); private isRetryableByDefault; toJSON(): { name: string; code: KMessageErrorCode; message: string; context: KMessageErrorContext; retryable: boolean; statusCode: number | undefined; stack: string | undefined; }; } declare class ProviderError extends KMessageError { constructor(providerId: string, code: KMessageErrorCode, message: string, context?: Omit<KMessageErrorContext, 'providerId'>, options?: { retryable?: boolean; statusCode?: number; cause?: Error; }); } declare class TemplateError extends KMessageError { constructor(templateCode: string, code: KMessageErrorCode, message: string, context?: Omit<KMessageErrorContext, 'templateCode'>, options?: { retryable?: boolean; statusCode?: number; cause?: Error; }); } declare class MessageError extends KMessageError { constructor(phoneNumber: string, code: KMessageErrorCode, message: string, context?: Omit<KMessageErrorContext, 'phoneNumber'>, options?: { retryable?: boolean; statusCode?: number; cause?: Error; }); } /** * Error factory functions for common error scenarios */ declare const ErrorFactory: { providerNotFound: (providerId: string) => ProviderError; providerNotAvailable: (providerId: string, reason?: string) => ProviderError; authenticationFailed: (providerId: string, details?: string) => ProviderError; templateNotFound: (templateCode: string) => TemplateError; invalidPhoneNumber: (phoneNumber: string) => MessageError; networkTimeout: (providerId?: string, timeout?: number) => KMessageError; rateLimited: (providerId: string, retryAfter?: number) => ProviderError; insufficientBalance: (providerId: string, balance?: string) => ProviderError; fromHttpStatus: (statusCode: number, message: string, context?: KMessageErrorContext) => KMessageError; }; /** * Result wrapper for operations that can fail */ type Result<T, E = KMessageError> = { success: true; data: T; } | { success: false; error: E; }; declare const Result: { success: <T>(data: T) => Result<T>; failure: <E = KMessageError>(error: E) => Result<never, E>; fromPromise: <T>(promise: Promise<T>) => Promise<Result<T>>; }; /** * Error handling utilities */ declare const ErrorUtils: { isRetryable: (error: Error) => boolean; getStatusCode: (error: Error) => number; formatErrorForClient: (error: Error) => { code: KMessageErrorCode; message: string; retryable: boolean; context: KMessageErrorContext; }; formatErrorForLogging: (error: Error) => { name: string; message: string; stack: string | undefined; } | { code: KMessageErrorCode; context: KMessageErrorContext; retryable: boolean; statusCode: number | undefined; name: string; message: string; stack: string | undefined; }; }; /** * Test utilities for K-Message Platform */ /** * Mock provider for testing */ declare class MockProvider implements BaseProvider { readonly id: string; readonly name: string; private _healthy; private _issues; private _balance; private _templates; private _history; constructor(id?: string, name?: string); healthCheck(): Promise<ProviderHealthStatus>; setHealthy(healthy: boolean, issues?: string[]): void; setBalance(balance: string): void; setTemplates(templates: any[]): void; setHistory(history: any[]): void; sendMessage(templateCode: string, phoneNumber: string, variables: Record<string, any>, options?: any): Promise<{ success: boolean; messageId: string; status: string; error: null; }>; getTemplates(page?: number, size?: number, filters?: any): Promise<{ code: number; message: string; totalCount: number; list: any[]; }>; createTemplate(name: string, content: string, category?: string, buttons?: any[]): Promise<{ success: boolean; templateCode: string; status: string; error: null; }>; modifyTemplate(templateCode: string, name: string, content: string, buttons?: any[]): Promise<{ success: boolean; templateCode: string; status: string; error: null; }>; deleteTemplate(templateCode: string): Promise<{ code: number; message: string; }>; getHistory(page?: number, size?: number, filters?: any): Promise<{ code: number; message: string; totalCount: number; list: any[]; }>; cancelReservation(messageId: string): Promise<{ code: number; message: string; }>; } /** * Test assertion helpers */ declare const TestAssertions: { /** * Assert that an error is a KMessageError with specific code */ assertKMessageError: (error: unknown, expectedCode: KMessageErrorCode, expectedMessage?: string) => void; /** * Assert that an error is retryable */ assertRetryable: (error: KMessageError, expected?: boolean) => void; /** * Assert that a health status is healthy */ assertHealthy: (health: ProviderHealthStatus | PlatformHealthStatus, expected?: boolean) => void; /** * Assert that a provider result has expected structure */ assertProviderResult: (result: any, expectSuccess?: boolean) => void; /** * Assert that API response has expected structure */ assertApiResponse: (response: any, expectedCode?: number) => void; }; /** * Test data generators */ declare const TestData: { createMockTemplate: (overrides?: Partial<any>) => { templateCode: string; templateName: string; templateContent: string; status: string; createDate: string; }; createMockMessage: (overrides?: Partial<any>) => { seqNo: number; phone: string; templateCode: string; statusCode: string; statusCodeName: string; requestDate: string; sendDate: string; receiveDate: string; sendMessage: string; }; createMockVariables: (overrides?: Record<string, any>) => { 서비스명: string; 고객명: string; 인증코드: string; }; generatePhoneNumber: (valid?: boolean) => string; }; /** * Test environment setup helpers */ declare const TestSetup: { /** * Create a test environment with mock providers */ createTestEnvironment: () => { providers: { healthy: MockProvider; unhealthy: MockProvider; rateLimited: MockProvider; }; cleanup: () => void; }; /** * Create test data for various scenarios */ createTestScenarios: () => { validMessage: { templateCode: string; phoneNumber: string; variables: { 서비스명: string; 고객명: string; 인증코드: string; }; }; invalidMessage: { templateCode: string; phoneNumber: string; variables: {}; }; templates: { templateCode: string; templateName: string; templateContent: string; status: string; createDate: string; }[]; history: { seqNo: number; phone: string; templateCode: string; statusCode: string; statusCodeName: string; requestDate: string; sendDate: string; receiveDate: string; sendMessage: string; }[]; }; }; /** * Performance testing helpers */ declare const PerformanceTest: { /** * Measure execution time of a function */ measureTime: <T>(fn: () => Promise<T>) => Promise<{ result: T; duration: number; }>; /** * Run a function multiple times and get statistics */ benchmark: <T>(fn: () => Promise<T>, iterations?: number) => Promise<{ results: T[]; statistics: { min: number; max: number; average: number; median: number; }; }>; }; /** * Error recovery and retry patterns for K-Message Platform */ interface RetryOptions { maxAttempts: number; initialDelay: number; maxDelay: number; backoffMultiplier: number; jitter: boolean; retryCondition?: (error: Error, attempt: number) => boolean; onRetry?: (error: Error, attempt: number) => void; } interface CircuitBreakerOptions { failureThreshold: number; timeout: number; resetTimeout: number; onOpen?: () => void; onHalfOpen?: () => void; onClose?: () => void; } interface BulkOperationOptions { concurrency: number; retryOptions: RetryOptions; failFast: boolean; onProgress?: (completed: number, total: number, failed: number) => void; } /** * Exponential backoff retry mechanism */ declare class RetryHandler { private static defaultOptions; static execute<T>(operation: () => Promise<T>, options?: Partial<RetryOptions>): Promise<T>; static createRetryableFunction<T extends any[], R>(func: (...args: T) => Promise<R>, options?: Partial<RetryOptions>): (...args: T) => Promise<R>; } /** * Circuit breaker pattern implementation */ declare class CircuitBreaker { private options; private state; private failureCount; private lastFailureTime; private nextAttemptTime; constructor(options: CircuitBreakerOptions); execute<T>(operation: () => Promise<T>): Promise<T>; private recordFailure; getState(): string; getFailureCount(): number; reset(): void; } /** * Bulk operation handler with error recovery */ declare class BulkOperationHandler { static execute<T, R>(items: T[], operation: (item: T) => Promise<R>, options?: Partial<BulkOperationOptions>): Promise<{ successful: { item: T; result: R; }[]; failed: { item: T; error: Error; }[]; summary: { total: number; successful: number; failed: number; duration: number; }; }>; private static createBatches; } /** * Rate limiter for API calls */ declare class RateLimiter { private maxRequests; private windowMs; private requests; constructor(maxRequests: number, windowMs: number); acquire(): Promise<void>; canMakeRequest(): boolean; getRemainingRequests(): number; } /** * Health check monitor with automatic recovery */ declare class HealthMonitor { private services; private healthStatus; private lastCheck; private checkInterval; private intervalId?; constructor(services: Map<string, () => Promise<boolean>>, checkIntervalMs?: number); start(): void; stop(): void; private checkAllServices; getServiceHealth(serviceName: string): boolean | undefined; getAllHealth(): Record<string, boolean>; isServiceHealthy(serviceName: string): boolean; getLastCheckTime(serviceName: string): number | undefined; } /** * Graceful degradation handler */ declare class GracefulDegradation { private fallbackStrategies; registerFallback<T>(operationName: string, fallbackFunction: () => Promise<T>): void; executeWithFallback<T>(operationName: string, primaryOperation: () => Promise<T>, options?: { timeout?: number; retryOptions?: Partial<RetryOptions>; }): Promise<T>; } /** * Error recovery utilities */ declare const ErrorRecovery: { /** * Create a resilient function that combines multiple recovery patterns */ createResilientFunction<T extends any[], R>(func: (...args: T) => Promise<R>, options?: { retryOptions?: Partial<RetryOptions>; circuitBreaker?: CircuitBreakerOptions; rateLimiter?: { maxRequests: number; windowMs: number; }; timeout?: number; fallback?: (...args: T) => Promise<R>; }): (...args: T) => Promise<R>; }; /** * Core AlimTalk Platform types and interfaces */ interface ProviderHealthStatus { healthy: boolean; issues: string[]; data?: { balance?: string; status?: string; code?: number; message?: string; }; } interface PlatformHealthStatus { healthy: boolean; providers: Record<string, boolean>; issues: string[]; } interface PlatformInfo { version: string; providers: string[]; features: string[]; } interface MessageSendOptions { templateId: string; recipients: { phoneNumber: string; variables?: Record<string, any>; }[]; variables: Record<string, any>; } interface MessageSendResult { results: Array<{ messageId?: string; status: string; phoneNumber: string; error?: { message: string; }; }>; summary: { total: number; sent: number; failed: number; }; } interface BaseProvider { id: string; name: string; healthCheck(): Promise<ProviderHealthStatus>; sendMessage?(templateCode: string, phoneNumber: string, variables: Record<string, any>, options?: any): Promise<any>; getTemplates?(page: number, size: number, filters?: any): Promise<any>; createTemplate?(name: string, content: string, category?: string, buttons?: any[]): Promise<any>; modifyTemplate?(templateCode: string, name: string, content: string, buttons?: any[]): Promise<any>; deleteTemplate?(templateCode: string): Promise<any>; getHistory?(page: number, size: number, filters?: any): Promise<any>; cancelReservation?(messageId: string): Promise<any>; } /** * Core AlimTalk Platform interface */ interface IAlimTalkPlatform { getInfo(): PlatformInfo; registerProvider(provider: BaseProvider): void; getProvider(providerId: string): BaseProvider | null; listProviders(): string[]; healthCheck(): Promise<PlatformHealthStatus>; messages: { send(options: MessageSendOptions): Promise<MessageSendResult>; getStatus(messageId: string): Promise<string>; }; } /** * Configuration interface */ interface PlatformConfig { providers: string[]; defaultProvider: string; features: { enableBulkSending?: boolean; enableScheduling?: boolean; enableAnalytics?: boolean; }; } /** * Template categories */ declare enum TemplateCategory { AUTHENTICATION = "AUTHENTICATION", NOTIFICATION = "NOTIFICATION", PROMOTION = "PROMOTION", INFORMATION = "INFORMATION", RESERVATION = "RESERVATION", SHIPPING = "SHIPPING", PAYMENT = "PAYMENT" } export { type BaseProvider, BulkOperationHandler, type BulkOperationOptions, CircuitBreaker, type CircuitBreakerOptions, ErrorFactory, ErrorRecovery, ErrorUtils, GracefulDegradation, HealthMonitor, type IAlimTalkPlatform, KMessageError, KMessageErrorCode, type KMessageErrorContext, MessageError, type MessageSendOptions, type MessageSendResult, MockProvider, PerformanceTest, type PlatformConfig, type PlatformHealthStatus, type PlatformInfo, ProviderError, type ProviderHealthStatus, RateLimiter, Result, RetryHandler, type RetryOptions, TemplateCategory, TemplateError, TestAssertions, TestData, TestSetup };