@k-msg/webhook 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Delivery Store
3
+ * 웹훅 전달 기록 저장 및 관리
4
+ */
5
+ import { EventEmitter } from "events";
6
+ import type { WebhookDelivery } from "../types/webhook.types";
7
+ import type { DeliveryFilter, PaginationOptions, SearchResult, StorageConfig } from "./types";
8
+ export declare class DeliveryStore extends EventEmitter {
9
+ private config;
10
+ private deliveries;
11
+ private indexByEndpoint;
12
+ private indexByStatus;
13
+ private indexByDate;
14
+ private cleanupInterval;
15
+ private defaultConfig;
16
+ constructor(config?: Partial<StorageConfig>);
17
+ /**
18
+ * 전달 기록 저장
19
+ */
20
+ saveDelivery(delivery: WebhookDelivery): Promise<void>;
21
+ /**
22
+ * 전달 기록 조회
23
+ */
24
+ getDelivery(deliveryId: string): Promise<WebhookDelivery | null>;
25
+ /**
26
+ * 필터 조건에 맞는 전달 기록 검색
27
+ */
28
+ searchDeliveries(filter?: DeliveryFilter, pagination?: PaginationOptions): Promise<SearchResult<WebhookDelivery>>;
29
+ /**
30
+ * 엔드포인트별 전달 기록 조회
31
+ */
32
+ getDeliveriesByEndpoint(endpointId: string, limit?: number): Promise<WebhookDelivery[]>;
33
+ /**
34
+ * 실패한 전달 기록 조회
35
+ */
36
+ getFailedDeliveries(endpointId?: string, limit?: number): Promise<WebhookDelivery[]>;
37
+ /**
38
+ * 전달 통계 조회
39
+ */
40
+ getDeliveryStats(endpointId?: string, timeRange?: {
41
+ start: Date;
42
+ end: Date;
43
+ }): Promise<{
44
+ totalDeliveries: number;
45
+ successfulDeliveries: number;
46
+ failedDeliveries: number;
47
+ pendingDeliveries: number;
48
+ exhaustedDeliveries: number;
49
+ averageLatency: number;
50
+ successRate: number;
51
+ errorBreakdown: Record<string, number>;
52
+ }>;
53
+ /**
54
+ * 오래된 전달 기록 정리
55
+ */
56
+ cleanupOldDeliveries(): Promise<number>;
57
+ /**
58
+ * 저장소 통계 조회
59
+ */
60
+ getStorageStats(): {
61
+ totalDeliveries: number;
62
+ memoryUsage: number;
63
+ indexSizes: {
64
+ byEndpoint: number;
65
+ byStatus: number;
66
+ byDate: number;
67
+ };
68
+ };
69
+ /**
70
+ * 인덱스 초기화
71
+ */
72
+ private initializeIndexes;
73
+ /**
74
+ * 인덱스에 전달 기록 추가
75
+ */
76
+ private addToIndexes;
77
+ /**
78
+ * 인덱스에서 전달 기록 제거
79
+ */
80
+ private removeFromIndexes;
81
+ /**
82
+ * 날짜 범위로 전달 기록 ID 조회
83
+ */
84
+ private getDeliveryIdsByDateRange;
85
+ /**
86
+ * 필터 조건 매칭 확인
87
+ */
88
+ private matchesFilter;
89
+ /**
90
+ * 객체 필드 값 가져오기
91
+ */
92
+ private getFieldValue;
93
+ /**
94
+ * 메모리 사용량 추정
95
+ */
96
+ private estimateMemoryUsage;
97
+ /**
98
+ * 메모리 사용량 확인 및 정리
99
+ */
100
+ private checkMemoryUsage;
101
+ /**
102
+ * 정리 작업 시작
103
+ */
104
+ private startCleanupTask;
105
+ /**
106
+ * 파일에 전달 기록 추가
107
+ */
108
+ private appendToFile;
109
+ /**
110
+ * 파일에서 데이터 로드
111
+ */
112
+ private loadFromFile;
113
+ /**
114
+ * 파일에 데이터 저장
115
+ */
116
+ private saveToFile;
117
+ /**
118
+ * 전달 저장소 종료
119
+ */
120
+ shutdown(): Promise<void>;
121
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Endpoint Manager
3
+ * 웹훅 엔드포인트 관리를 위한 고급 기능 제공
4
+ */
5
+ import { EventEmitter } from "events";
6
+ import type { WebhookEndpoint } from "../types/webhook.types";
7
+ import { WebhookEventType } from "../types/webhook.types";
8
+ import type { EndpointFilter, PaginationOptions, SearchResult, StorageConfig } from "./types";
9
+ export declare class EndpointManager extends EventEmitter {
10
+ private config;
11
+ private endpoints;
12
+ private indexByUrl;
13
+ private indexByEvent;
14
+ private indexByStatus;
15
+ private defaultConfig;
16
+ constructor(config?: Partial<StorageConfig>);
17
+ /**
18
+ * 엔드포인트 추가
19
+ */
20
+ addEndpoint(endpoint: WebhookEndpoint): Promise<void>;
21
+ /**
22
+ * 엔드포인트 업데이트
23
+ */
24
+ updateEndpoint(endpointId: string, updates: Partial<WebhookEndpoint>): Promise<WebhookEndpoint>;
25
+ /**
26
+ * 엔드포인트 제거
27
+ */
28
+ removeEndpoint(endpointId: string): Promise<boolean>;
29
+ /**
30
+ * 엔드포인트 조회
31
+ */
32
+ getEndpoint(endpointId: string): Promise<WebhookEndpoint | null>;
33
+ /**
34
+ * URL로 엔드포인트 조회
35
+ */
36
+ getEndpointByUrl(url: string): Promise<WebhookEndpoint | null>;
37
+ /**
38
+ * 필터 조건에 맞는 엔드포인트 검색
39
+ */
40
+ searchEndpoints(filter?: EndpointFilter, pagination?: PaginationOptions): Promise<SearchResult<WebhookEndpoint>>;
41
+ /**
42
+ * 특정 이벤트 타입을 구독하는 활성 엔드포인트 조회
43
+ */
44
+ getActiveEndpointsForEvent(eventType: WebhookEventType): Promise<WebhookEndpoint[]>;
45
+ /**
46
+ * 엔드포인트 통계 조회
47
+ */
48
+ getStats(): {
49
+ totalEndpoints: number;
50
+ activeEndpoints: number;
51
+ inactiveEndpoints: number;
52
+ errorEndpoints: number;
53
+ suspendedEndpoints: number;
54
+ eventSubscriptions: Record<WebhookEventType, number>;
55
+ };
56
+ /**
57
+ * 만료된 엔드포인트 정리
58
+ */
59
+ cleanupExpiredEndpoints(): Promise<number>;
60
+ /**
61
+ * 인덱스 초기화
62
+ */
63
+ private initializeIndexes;
64
+ /**
65
+ * 인덱스에 엔드포인트 추가
66
+ */
67
+ private addToIndexes;
68
+ /**
69
+ * 인덱스에서 엔드포인트 제거
70
+ */
71
+ private removeFromIndexes;
72
+ /**
73
+ * 필터 조건 매칭 확인
74
+ */
75
+ private matchesFilter;
76
+ /**
77
+ * 객체 필드 값 가져오기 (정렬용)
78
+ */
79
+ private getFieldValue;
80
+ /**
81
+ * 파일에서 데이터 로드
82
+ */
83
+ private loadFromFile;
84
+ /**
85
+ * 파일에 데이터 저장
86
+ */
87
+ private saveToFile;
88
+ /**
89
+ * 엔드포인트 관리자 종료
90
+ */
91
+ shutdown(): Promise<void>;
92
+ }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Event Store
3
+ * 웹훅 이벤트 저장 및 관리
4
+ */
5
+ import { EventEmitter } from "events";
6
+ import type { WebhookEvent } from "../types/webhook.types";
7
+ import { WebhookEventType } from "../types/webhook.types";
8
+ import type { EventFilter, PaginationOptions, SearchResult, StorageConfig } from "./types";
9
+ export declare class EventStore extends EventEmitter {
10
+ private config;
11
+ private events;
12
+ private indexByType;
13
+ private indexByDate;
14
+ private indexByProvider;
15
+ private indexByChannel;
16
+ private cleanupInterval;
17
+ private defaultConfig;
18
+ constructor(config?: Partial<StorageConfig>);
19
+ /**
20
+ * 이벤트 저장
21
+ */
22
+ saveEvent(event: WebhookEvent): Promise<void>;
23
+ /**
24
+ * 이벤트 조회
25
+ */
26
+ getEvent(eventId: string): Promise<WebhookEvent | null>;
27
+ /**
28
+ * 필터 조건에 맞는 이벤트 검색
29
+ */
30
+ searchEvents(filter?: EventFilter, pagination?: PaginationOptions): Promise<SearchResult<WebhookEvent>>;
31
+ /**
32
+ * 이벤트 타입별 조회
33
+ */
34
+ getEventsByType(eventType: WebhookEventType, limit?: number): Promise<WebhookEvent[]>;
35
+ /**
36
+ * 이벤트 통계 조회
37
+ */
38
+ getEventStats(timeRange?: {
39
+ start: Date;
40
+ end: Date;
41
+ }): Promise<{
42
+ totalEvents: number;
43
+ eventsByType: Record<WebhookEventType, number>;
44
+ eventsByProvider: Record<string, number>;
45
+ eventsByChannel: Record<string, number>;
46
+ eventsPerHour: Record<string, number>;
47
+ }>;
48
+ /**
49
+ * 오래된 이벤트 정리
50
+ */
51
+ cleanupOldEvents(): Promise<number>;
52
+ /**
53
+ * 중복 이벤트 정리
54
+ */
55
+ cleanupDuplicateEvents(): Promise<number>;
56
+ /**
57
+ * 저장소 통계 조회
58
+ */
59
+ getStorageStats(): {
60
+ totalEvents: number;
61
+ memoryUsage: number;
62
+ indexSizes: {
63
+ byType: number;
64
+ byDate: number;
65
+ byProvider: number;
66
+ byChannel: number;
67
+ };
68
+ };
69
+ /**
70
+ * 인덱스 초기화
71
+ */
72
+ private initializeIndexes;
73
+ /**
74
+ * 인덱스에 이벤트 추가
75
+ */
76
+ private addToIndexes;
77
+ /**
78
+ * 인덱스에서 이벤트 제거
79
+ */
80
+ private removeFromIndexes;
81
+ /**
82
+ * 날짜 범위로 이벤트 ID 조회
83
+ */
84
+ private getEventIdsByDateRange;
85
+ /**
86
+ * 필터 조건 매칭 확인
87
+ */
88
+ private matchesFilter;
89
+ /**
90
+ * 객체 필드 값 가져오기
91
+ */
92
+ private getFieldValue;
93
+ /**
94
+ * 메모리 사용량 추정
95
+ */
96
+ private estimateMemoryUsage;
97
+ /**
98
+ * 메모리 사용량 확인 및 정리
99
+ */
100
+ private checkMemoryUsage;
101
+ /**
102
+ * 이벤트 내용 키 생성 (중복 검사용)
103
+ */
104
+ private generateContentKey;
105
+ /**
106
+ * 정리 작업 시작
107
+ */
108
+ private startCleanupTask;
109
+ /**
110
+ * 파일에 이벤트 추가
111
+ */
112
+ private appendToFile;
113
+ /**
114
+ * 파일에서 데이터 로드
115
+ */
116
+ private loadFromFile;
117
+ /**
118
+ * 파일에 데이터 저장
119
+ */
120
+ private saveToFile;
121
+ /**
122
+ * 이벤트 저장소 종료
123
+ */
124
+ shutdown(): Promise<void>;
125
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Webhook Registry Components
3
+ * 웹훅 엔드포인트 및 전달 기록 관리 관련 컴포넌트들
4
+ */
5
+ export { WebhookRegistry } from "../services/webhook.registry";
6
+ export { DeliveryStore } from "./delivery.store";
7
+ export { EndpointManager } from "./endpoint.manager";
8
+ export { EventStore } from "./event.store";
9
+ export type { DeliveryFilter, EndpointFilter, EventFilter, PaginationOptions, SearchResult, StorageConfig, } from "./types";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Registry Type Definitions
3
+ */
4
+ import type { WebhookEventType } from "../types/webhook.types";
5
+ export interface EndpointFilter {
6
+ status?: "active" | "inactive" | "error" | "suspended";
7
+ events?: WebhookEventType[];
8
+ providerId?: string[];
9
+ channelId?: string[];
10
+ createdAfter?: Date;
11
+ createdBefore?: Date;
12
+ lastTriggeredAfter?: Date;
13
+ lastTriggeredBefore?: Date;
14
+ }
15
+ export interface DeliveryFilter {
16
+ endpointId?: string;
17
+ eventId?: string;
18
+ status?: "pending" | "success" | "failed" | "exhausted";
19
+ createdAfter?: Date;
20
+ createdBefore?: Date;
21
+ completedAfter?: Date;
22
+ completedBefore?: Date;
23
+ httpStatusCode?: number[];
24
+ hasError?: boolean;
25
+ }
26
+ export interface EventFilter {
27
+ type?: WebhookEventType[];
28
+ providerId?: string[];
29
+ channelId?: string[];
30
+ templateId?: string[];
31
+ messageId?: string[];
32
+ userId?: string[];
33
+ organizationId?: string[];
34
+ createdAfter?: Date;
35
+ createdBefore?: Date;
36
+ }
37
+ export interface StorageConfig {
38
+ type: "memory" | "file" | "database";
39
+ filePath?: string;
40
+ enableCompression?: boolean;
41
+ maxFileSize?: number;
42
+ connectionString?: string;
43
+ tableName?: string;
44
+ maxMemoryUsage?: number;
45
+ retentionDays?: number;
46
+ enableEncryption?: boolean;
47
+ encryptionKey?: string;
48
+ }
49
+ export interface PaginationOptions {
50
+ page: number;
51
+ limit: number;
52
+ sortBy?: string;
53
+ sortOrder?: "asc" | "desc";
54
+ }
55
+ export interface SearchResult<T> {
56
+ items: T[];
57
+ totalCount: number;
58
+ page: number;
59
+ totalPages: number;
60
+ hasNext: boolean;
61
+ hasPrevious: boolean;
62
+ }
@@ -0,0 +1,61 @@
1
+ import type { WebhookConfig } from "../types/webhook.types";
2
+ export interface RetryConfig {
3
+ maxRetries: number;
4
+ baseDelayMs: number;
5
+ maxDelayMs: number;
6
+ backoffMultiplier: number;
7
+ jitter: boolean;
8
+ }
9
+ export interface RetryAttempt {
10
+ attemptNumber: number;
11
+ timestamp: Date;
12
+ success: boolean;
13
+ error?: string;
14
+ nextRetryAt?: Date;
15
+ }
16
+ /**
17
+ * Webhook 재시도 관리자
18
+ * 지수 백오프와 지터를 사용한 스마트 재시도 로직
19
+ */
20
+ export declare class RetryManager {
21
+ private config;
22
+ constructor(webhookConfig: WebhookConfig);
23
+ /**
24
+ * 다음 재시도 시간 계산
25
+ */
26
+ calculateNextRetry(attemptNumber: number): Date;
27
+ /**
28
+ * 재시도 가능 여부 확인
29
+ */
30
+ shouldRetry(attemptNumber: number, error?: Error): boolean;
31
+ /**
32
+ * 재시도 가능한 에러인지 판단
33
+ */
34
+ private isRetryableError;
35
+ /**
36
+ * HTTP 상태 코드별 재시도 정책
37
+ */
38
+ shouldRetryStatus(statusCode: number): boolean;
39
+ /**
40
+ * 재시도 통계 계산
41
+ */
42
+ calculateRetryStats(attempts: RetryAttempt[]): {
43
+ totalAttempts: number;
44
+ successfulAttempts: number;
45
+ failedAttempts: number;
46
+ averageDelayMs: number;
47
+ totalTimeMs: number;
48
+ };
49
+ /**
50
+ * 재시도 설정 업데이트
51
+ */
52
+ updateConfig(config: Partial<RetryConfig>): void;
53
+ /**
54
+ * 현재 재시도 설정 반환
55
+ */
56
+ getConfig(): RetryConfig;
57
+ /**
58
+ * 백오프 지연 시간 계산 (테스트용)
59
+ */
60
+ getBackoffDelay(attemptNumber: number): number;
61
+ }
@@ -0,0 +1,50 @@
1
+ import type { WebhookConfig } from "../types/webhook.types";
2
+ export interface SecurityConfig {
3
+ algorithm: "sha256" | "sha1";
4
+ header: string;
5
+ prefix?: string;
6
+ }
7
+ /**
8
+ * Webhook 보안 관리자
9
+ * 서명 생성 및 검증을 담당
10
+ */
11
+ export declare class SecurityManager {
12
+ private config;
13
+ constructor(webhookConfig: WebhookConfig);
14
+ /**
15
+ * Webhook 페이로드에 대한 서명 생성
16
+ */
17
+ generateSignature(payload: string, secret: string): string;
18
+ /**
19
+ * Webhook 서명 검증
20
+ */
21
+ verifySignature(payload: string, signature: string, secret: string): boolean;
22
+ /**
23
+ * HTTP 헤더에서 서명 추출
24
+ */
25
+ extractSignature(headers: Record<string, string>): string | null;
26
+ /**
27
+ * Webhook 전송을 위한 보안 헤더 생성
28
+ */
29
+ createSecurityHeaders(payload: string, secret: string): Record<string, string>;
30
+ /**
31
+ * 타임스탬프 기반 재생 공격 방지 검증
32
+ */
33
+ verifyTimestamp(timestamp: string, toleranceSeconds?: number): boolean;
34
+ /**
35
+ * Webhook ID 생성 (추적용)
36
+ */
37
+ private generateWebhookId;
38
+ /**
39
+ * Constant-time 문자열 비교 (타이밍 공격 방지)
40
+ */
41
+ private constantTimeCompare;
42
+ /**
43
+ * 보안 설정 업데이트
44
+ */
45
+ updateConfig(config: Partial<SecurityConfig>): void;
46
+ /**
47
+ * 현재 보안 설정 반환
48
+ */
49
+ getConfig(): SecurityConfig;
50
+ }
@@ -0,0 +1,26 @@
1
+ import type { WebhookConfig, WebhookDelivery, WebhookEndpoint, WebhookEvent } from "../types/webhook.types";
2
+ export interface HttpClient {
3
+ fetch(url: string, options: RequestInit): Promise<Response>;
4
+ }
5
+ export declare class DefaultHttpClient implements HttpClient {
6
+ fetch(url: string, options: RequestInit): Promise<Response>;
7
+ }
8
+ export declare class MockHttpClient implements HttpClient {
9
+ private responses;
10
+ setMockResponse(url: string, response: Response): void;
11
+ fetch(url: string, options: RequestInit): Promise<Response>;
12
+ }
13
+ export declare class WebhookDispatcher {
14
+ private config;
15
+ private httpClient;
16
+ constructor(config: WebhookConfig, httpClient?: HttpClient);
17
+ dispatch(event: WebhookEvent, endpoint: WebhookEndpoint): Promise<WebhookDelivery>;
18
+ private executeDelivery;
19
+ private makeHttpRequest;
20
+ private buildHeaders;
21
+ private generateSignature;
22
+ private calculateRetryDelay;
23
+ private sleep;
24
+ private generateDeliveryId;
25
+ shutdown(): Promise<void>;
26
+ }
@@ -0,0 +1,16 @@
1
+ import type { WebhookDelivery, WebhookEndpoint, WebhookEventType } from "../types/webhook.types";
2
+ export declare class WebhookRegistry {
3
+ private endpoints;
4
+ private deliveries;
5
+ addEndpoint(endpoint: WebhookEndpoint): Promise<void>;
6
+ updateEndpoint(endpointId: string, endpoint: WebhookEndpoint): Promise<void>;
7
+ removeEndpoint(endpointId: string): Promise<void>;
8
+ getEndpoint(endpointId: string): Promise<WebhookEndpoint | null>;
9
+ listEndpoints(): Promise<WebhookEndpoint[]>;
10
+ addDelivery(delivery: WebhookDelivery): Promise<void>;
11
+ getDeliveries(endpointId?: string, timeRange?: {
12
+ start: Date;
13
+ end: Date;
14
+ }, eventType?: WebhookEventType, status?: string, limit?: number): Promise<WebhookDelivery[]>;
15
+ getFailedDeliveries(endpointId?: string, eventType?: WebhookEventType): Promise<WebhookDelivery[]>;
16
+ }
@@ -0,0 +1,78 @@
1
+ import type { WebhookConfig, WebhookDelivery, WebhookEndpoint, WebhookEvent, WebhookStats, WebhookTestResult } from "../types/webhook.types";
2
+ import { WebhookEventType } from "../types/webhook.types";
3
+ import { type HttpClient } from "./webhook.dispatcher";
4
+ export declare class WebhookService {
5
+ private config;
6
+ private dispatcher;
7
+ private registry;
8
+ private securityManager;
9
+ private retryManager;
10
+ private eventQueue;
11
+ private batchProcessor;
12
+ constructor(config: WebhookConfig, httpClient?: HttpClient);
13
+ /**
14
+ * 웹훅 엔드포인트 등록
15
+ */
16
+ registerEndpoint(endpoint: Omit<WebhookEndpoint, "id" | "createdAt" | "updatedAt" | "status">): Promise<WebhookEndpoint>;
17
+ /**
18
+ * 웹훅 엔드포인트 수정
19
+ */
20
+ updateEndpoint(endpointId: string, updates: Partial<WebhookEndpoint>): Promise<WebhookEndpoint>;
21
+ /**
22
+ * 웹훅 엔드포인트 삭제
23
+ */
24
+ deleteEndpoint(endpointId: string): Promise<void>;
25
+ /**
26
+ * 웹훅 엔드포인트 조회
27
+ */
28
+ getEndpoint(endpointId: string): Promise<WebhookEndpoint | null>;
29
+ /**
30
+ * 모든 웹훅 엔드포인트 조회
31
+ */
32
+ listEndpoints(): Promise<WebhookEndpoint[]>;
33
+ /**
34
+ * 이벤트 발생 (비동기 처리)
35
+ */
36
+ emit(event: WebhookEvent): Promise<void>;
37
+ /**
38
+ * 이벤트 발생 (동기 처리)
39
+ */
40
+ emitSync(event: WebhookEvent): Promise<WebhookDelivery[]>;
41
+ /**
42
+ * 웹훅 엔드포인트 테스트
43
+ */
44
+ testEndpoint(endpointId: string): Promise<WebhookTestResult>;
45
+ /**
46
+ * 웹훅 통계 조회
47
+ */
48
+ getStats(endpointId: string, timeRange: {
49
+ start: Date;
50
+ end: Date;
51
+ }): Promise<WebhookStats>;
52
+ /**
53
+ * 실패한 웹훅 재시도
54
+ */
55
+ retryFailed(endpointId?: string, eventType?: WebhookEventType): Promise<number>;
56
+ /**
57
+ * 웹훅 일시 중단
58
+ */
59
+ pauseEndpoint(endpointId: string): Promise<void>;
60
+ /**
61
+ * 웹훅 재개
62
+ */
63
+ resumeEndpoint(endpointId: string): Promise<void>;
64
+ /**
65
+ * 웹훅 전달 내역 조회
66
+ */
67
+ getDeliveries(endpointId?: string, eventType?: WebhookEventType, status?: string, limit?: number): Promise<WebhookDelivery[]>;
68
+ private processBatch;
69
+ private getMatchingEndpoints;
70
+ private validateEvent;
71
+ private validateEndpointUrl;
72
+ private generateEndpointId;
73
+ private startBatchProcessor;
74
+ /**
75
+ * 서비스 종료 시 정리
76
+ */
77
+ shutdown(): Promise<void>;
78
+ }