@k-msg/provider 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.
Files changed (47) hide show
  1. package/README.md +3 -1
  2. package/dist/abstract/provider.base.d.ts +108 -0
  3. package/dist/adapters/aligo.adapter.d.ts +50 -0
  4. package/dist/adapters/iwinv.adapter.d.ts +111 -0
  5. package/dist/aligo/provider.d.ts +18 -0
  6. package/dist/config/provider-config-v2.d.ts +122 -0
  7. package/dist/contracts/provider.contract.d.ts +355 -0
  8. package/dist/contracts/sms.contract.d.ts +135 -0
  9. package/dist/index.d.ts +29 -1424
  10. package/dist/index.js +21 -2003
  11. package/dist/index.js.map +98 -1
  12. package/dist/index.mjs +25 -0
  13. package/dist/index.mjs.map +98 -0
  14. package/dist/interfaces/index.d.ts +14 -0
  15. package/dist/interfaces/plugin.d.ts +122 -0
  16. package/dist/interfaces/services.d.ts +222 -0
  17. package/dist/iwinv/contracts/account.contract.d.ts +11 -0
  18. package/dist/iwinv/contracts/analytics.contract.d.ts +16 -0
  19. package/dist/iwinv/contracts/channel.contract.d.ts +15 -0
  20. package/dist/iwinv/contracts/messaging.contract.d.ts +14 -0
  21. package/dist/iwinv/contracts/sms.contract.d.ts +33 -0
  22. package/dist/iwinv/contracts/template.contract.d.ts +18 -0
  23. package/dist/iwinv/index.d.ts +5 -0
  24. package/dist/iwinv/provider-multi.d.ts +116 -0
  25. package/dist/iwinv/provider-sms.d.ts +55 -0
  26. package/dist/iwinv/provider.d.ts +42 -0
  27. package/dist/iwinv/types/iwinv.d.ts +153 -0
  28. package/dist/middleware/index.d.ts +27 -0
  29. package/dist/mock/index.d.ts +1 -0
  30. package/dist/providers/mock/index.d.ts +1 -0
  31. package/dist/providers/mock/mock.provider.d.ts +22 -0
  32. package/dist/registry/index.d.ts +1 -0
  33. package/dist/registry/plugin-registry.d.ts +15 -0
  34. package/dist/services/provider.manager.d.ts +24 -0
  35. package/dist/services/provider.service.d.ts +49 -0
  36. package/dist/test-helpers.d.ts +110 -0
  37. package/dist/types/aligo.d.ts +69 -0
  38. package/dist/types/base.d.ts +172 -0
  39. package/dist/types/typed-templates.d.ts +199 -0
  40. package/dist/types/unified-config.d.ts +197 -0
  41. package/dist/types/unified-errors.d.ts +225 -0
  42. package/dist/utils/base-plugin.d.ts +35 -0
  43. package/dist/utils/index.d.ts +12 -0
  44. package/package.json +25 -14
  45. package/dist/index.cjs +0 -2061
  46. package/dist/index.cjs.map +0 -1
  47. package/dist/index.d.cts +0 -1425
@@ -0,0 +1,153 @@
1
+ /**
2
+ * IWINV API TypeScript 타입 정의
3
+ * IWINV 알림톡 REST API 규격서 기반
4
+ */
5
+ export interface IWINVBaseResponse {
6
+ code: number;
7
+ message: string;
8
+ }
9
+ export interface SendMessageRequest {
10
+ templateCode: string;
11
+ reserve?: "Y" | "N";
12
+ sendDate?: string;
13
+ reSend?: "Y" | "N";
14
+ resendCallback?: string;
15
+ resendType?: "Y" | "N";
16
+ resendTitle?: string;
17
+ resendContent?: string;
18
+ list: SendRecipient[];
19
+ }
20
+ export interface SendRecipient {
21
+ phone: string;
22
+ templateParam?: string[];
23
+ }
24
+ export interface SendMessageResponse extends IWINVBaseResponse {
25
+ success: number;
26
+ fail: number;
27
+ }
28
+ export interface CreateTemplateRequest {
29
+ templateName: string;
30
+ templateContent: string;
31
+ buttons?: CreateTemplateButton[];
32
+ }
33
+ export interface CreateTemplateButton {
34
+ type: "WL" | "AL" | "DB" | "BK" | "MD";
35
+ name: string;
36
+ linkMo?: string;
37
+ linkPc?: string;
38
+ linkIos?: string;
39
+ linkAnd?: string;
40
+ }
41
+ export interface Template {
42
+ templateCode: string;
43
+ templateName: string;
44
+ templateContent: string;
45
+ status: "Y" | "I" | "R";
46
+ templateStatusMsg?: string;
47
+ templateStatusComments?: string;
48
+ createDate: string;
49
+ buttons: any[];
50
+ }
51
+ export interface TemplateListRequest {
52
+ pageNum?: string;
53
+ pageSize?: string;
54
+ templateCode?: string;
55
+ templateName?: string;
56
+ templateStatus?: "Y" | "I" | "R";
57
+ }
58
+ export interface TemplateListResponse extends IWINVBaseResponse {
59
+ totalCount: number;
60
+ list: Template[];
61
+ }
62
+ export interface ModifyTemplateRequest {
63
+ templateCode: string;
64
+ templateName: string;
65
+ templateContent: string;
66
+ buttons?: CreateTemplateButton[];
67
+ }
68
+ export interface DeleteTemplateRequest {
69
+ templateCode: string;
70
+ }
71
+ export type CreateTemplateResponse = IWINVBaseResponse;
72
+ export type ModifyTemplateResponse = IWINVBaseResponse;
73
+ export type DeleteTemplateResponse = IWINVBaseResponse;
74
+ export interface HistoryRequest {
75
+ pageNum?: number;
76
+ pageSize?: number;
77
+ reserve?: "Y" | "N";
78
+ startDate?: string;
79
+ endDate?: string;
80
+ seqNo?: number;
81
+ phone?: string;
82
+ }
83
+ export interface MessageHistory {
84
+ seqNo: number;
85
+ phone: string;
86
+ callback: string;
87
+ templateCode: string;
88
+ sendMessage: string;
89
+ reserve: "Y" | "N";
90
+ requestDate: string;
91
+ sendDate: string;
92
+ receiveDate: string;
93
+ statusCode: string;
94
+ statusCodeName: string;
95
+ resendStatus: string | null;
96
+ resendStatusName: string | null;
97
+ buttons: {
98
+ link1: string | null;
99
+ link2: string | null;
100
+ link3: string | null;
101
+ link4: string | null;
102
+ link5: string | null;
103
+ };
104
+ }
105
+ export interface HistoryResponse extends IWINVBaseResponse {
106
+ totalCount: number;
107
+ list: MessageHistory[];
108
+ }
109
+ export interface CancelReservationRequest {
110
+ seqNo: number;
111
+ }
112
+ export type CancelReservationResponse = IWINVBaseResponse;
113
+ export interface BalanceResponse extends IWINVBaseResponse {
114
+ charge: number;
115
+ }
116
+ export interface IWINVConfig {
117
+ apiKey: string;
118
+ baseUrl: string;
119
+ smsApiKey?: string;
120
+ smsAuthKey?: string;
121
+ smsBaseUrl?: string;
122
+ senderNumber?: string;
123
+ smsSenderNumber?: string;
124
+ sendEndpoint?: string;
125
+ ipRetryCount?: number;
126
+ ipRetryDelayMs?: number;
127
+ ipAlertWebhookUrl?: string;
128
+ onIpRestrictionAlert?: (payload: IWINVIPRestrictionAlert) => void | Promise<void>;
129
+ debug?: boolean;
130
+ [key: string]: unknown;
131
+ }
132
+ export interface IWINVIPRestrictionAlert {
133
+ provider: "iwinv";
134
+ channel: string;
135
+ endpoint: string;
136
+ phoneNumber: string;
137
+ templateCode?: string;
138
+ code: string;
139
+ message: string;
140
+ attempt: number;
141
+ maxAttempts: number;
142
+ timestamp: string;
143
+ }
144
+ export declare const IWINV_STATUS_CODES: {
145
+ readonly SUCCESS: 200;
146
+ readonly AUTH_FAILED: 201;
147
+ readonly BAD_REQUEST: 400;
148
+ readonly UNAUTHORIZED: 401;
149
+ readonly FORBIDDEN: 403;
150
+ readonly NOT_FOUND: 404;
151
+ readonly TOO_MANY_REQUESTS: 429;
152
+ readonly INTERNAL_SERVER_ERROR: 500;
153
+ };
@@ -0,0 +1,27 @@
1
+ import type { ProviderMiddleware } from "../interfaces";
2
+ export declare function createRetryMiddleware(options: {
3
+ maxRetries: number;
4
+ retryDelay: number;
5
+ retryableErrors?: string[];
6
+ retryableStatusCodes?: number[];
7
+ }): ProviderMiddleware;
8
+ export declare function createRateLimitMiddleware(options: {
9
+ messagesPerSecond?: number;
10
+ messagesPerMinute?: number;
11
+ messagesPerHour?: number;
12
+ messagesPerDay?: number;
13
+ strategy?: "sliding-window" | "fixed-window";
14
+ }): ProviderMiddleware;
15
+ export declare function createLoggingMiddleware(options: {
16
+ logger: any;
17
+ logLevel?: string;
18
+ }): ProviderMiddleware;
19
+ export declare function createMetricsMiddleware(options: {
20
+ collector: any;
21
+ labels?: Record<string, string>;
22
+ }): ProviderMiddleware;
23
+ export declare function createCircuitBreakerMiddleware(options: {
24
+ threshold: number;
25
+ timeout: number;
26
+ resetTimeout: number;
27
+ }): ProviderMiddleware;
@@ -0,0 +1 @@
1
+ export * from "../providers/mock";
@@ -0,0 +1 @@
1
+ export * from "./mock.provider";
@@ -0,0 +1,22 @@
1
+ import { KMsgError, type Provider, type Result, type SendOptions, type SendResult, type Template, type TemplateProvider } from "@k-msg/core";
2
+ export declare class MockProvider implements Provider, TemplateProvider {
3
+ readonly id = "mock";
4
+ readonly name = "Mock Provider";
5
+ calls: SendOptions[];
6
+ private failureCount;
7
+ private templates;
8
+ send(params: SendOptions): Promise<Result<SendResult, KMsgError>>;
9
+ mockSuccess(): void;
10
+ mockFailure(count: number): void;
11
+ getHistory(): SendOptions[];
12
+ clearHistory(): void;
13
+ createTemplate(template: Omit<Template, "id" | "status" | "createdAt" | "updatedAt">): Promise<Result<Template, KMsgError>>;
14
+ updateTemplate(code: string, template: Partial<Omit<Template, "id" | "code" | "status" | "createdAt" | "updatedAt">>): Promise<Result<Template, KMsgError>>;
15
+ deleteTemplate(code: string): Promise<Result<void, KMsgError>>;
16
+ getTemplate(code: string): Promise<Result<Template, KMsgError>>;
17
+ listTemplates(params?: {
18
+ status?: string;
19
+ page?: number;
20
+ limit?: number;
21
+ }): Promise<Result<Template[], KMsgError>>;
22
+ }
@@ -0,0 +1 @@
1
+ export * from "./plugin-registry";
@@ -0,0 +1,15 @@
1
+ import type { Logger, MetricsCollector, PluginStorage, ProviderConfig, ProviderPlugin } from "../interfaces";
2
+ export declare class PluginRegistry {
3
+ private plugins;
4
+ private instances;
5
+ register(plugin: ProviderPlugin): void;
6
+ create(pluginId: string, config: ProviderConfig, options?: {
7
+ logger?: Logger;
8
+ metrics?: MetricsCollector;
9
+ storage?: PluginStorage;
10
+ }): Promise<ProviderPlugin>;
11
+ loadAndCreate(pluginId: string, config: ProviderConfig, options?: any): Promise<ProviderPlugin>;
12
+ getSupportedTypes(): string[];
13
+ validateProviderConfig(type: string, config: ProviderConfig): boolean;
14
+ destroyAll(): Promise<void>;
15
+ }
@@ -0,0 +1,24 @@
1
+ import type { BaseProvider, ProviderType, StandardRequest, StandardResult } from "@k-msg/core";
2
+ import type { AlimTalkProvider, AlimTalkRequest, AlimTalkResult } from "../contracts/provider.contract";
3
+ import type { SMSProvider, SMSRequest, SMSResult } from "../contracts/sms.contract";
4
+ export declare class ProviderManager {
5
+ private providers;
6
+ private defaultProvider?;
7
+ registerProvider(provider: BaseProvider<StandardRequest, StandardResult>): void;
8
+ unregisterProvider(providerId: string): void;
9
+ getProvider(providerId?: string): BaseProvider<StandardRequest, StandardResult> | null;
10
+ getAlimTalkProvider(providerId?: string): AlimTalkProvider | null;
11
+ listProviders(): BaseProvider<StandardRequest, StandardResult>[];
12
+ listAlimTalkProviders(): AlimTalkProvider[];
13
+ setDefaultProvider(providerId: string): void;
14
+ healthCheckAll(): Promise<Record<string, boolean>>;
15
+ getProvidersForChannel(channel: string): BaseProvider<StandardRequest, StandardResult>[];
16
+ getProvidersByType(type: ProviderType): BaseProvider<StandardRequest, StandardResult>[];
17
+ getSMSProvider(providerId?: string): SMSProvider | null;
18
+ listSMSProviders(): SMSProvider[];
19
+ send<TRequest extends StandardRequest, TResult extends StandardResult>(providerId: string, request: TRequest): Promise<TResult>;
20
+ sendAlimTalk(providerId: string | undefined, request: AlimTalkRequest): Promise<AlimTalkResult>;
21
+ sendSMS(providerId: string | undefined, request: SMSRequest): Promise<SMSResult>;
22
+ private isAlimTalkProvider;
23
+ private isSMSProvider;
24
+ }
@@ -0,0 +1,49 @@
1
+ import type { BaseProvider, StandardRequest, StandardResult } from "@k-msg/core";
2
+ import type { AlimTalkProvider, AlimTalkRequest, AlimTalkResult } from "../contracts/provider.contract";
3
+ /**
4
+ * Manages the lifecycle and access to different messaging providers.
5
+ */
6
+ export declare class ProviderService {
7
+ private providers;
8
+ private defaultProviderId?;
9
+ /**
10
+ * @param defaultProviderId The ID of the provider to use when none is specified.
11
+ */
12
+ constructor(defaultProviderId?: string);
13
+ /**
14
+ * Registers a new provider instance.
15
+ * If no default provider is set, the first registered provider becomes the default.
16
+ * @param provider The provider instance to register.
17
+ */
18
+ register(provider: BaseProvider<StandardRequest, StandardResult>): void;
19
+ /**
20
+ * Retrieves a provider by its unique ID.
21
+ * @param providerId The ID of the provider.
22
+ * @returns The provider instance or undefined if not found.
23
+ */
24
+ get(providerId: string): BaseProvider<StandardRequest, StandardResult> | undefined;
25
+ /**
26
+ * Retrieves a typed AlimTalk provider by its unique ID.
27
+ * @param providerId The ID of the provider.
28
+ * @returns The AlimTalk provider instance or undefined if not found or not an AlimTalk provider.
29
+ */
30
+ getAlimTalk(providerId: string): AlimTalkProvider | undefined;
31
+ /**
32
+ * Retrieves the default provider.
33
+ * @returns The default provider instance or undefined if not set.
34
+ */
35
+ getDefault(): BaseProvider<StandardRequest, StandardResult> | undefined;
36
+ /**
37
+ * Lists all registered providers.
38
+ * @returns An array of all provider instances.
39
+ */
40
+ list(): BaseProvider<StandardRequest, StandardResult>[];
41
+ /**
42
+ * Lists all AlimTalk providers.
43
+ * @returns An array of AlimTalk provider instances.
44
+ */
45
+ listAlimTalk(): AlimTalkProvider[];
46
+ send<TRequest extends StandardRequest, TResult extends StandardResult>(providerId: string, request: TRequest): Promise<TResult>;
47
+ sendAlimTalk(providerId: string, request: AlimTalkRequest): Promise<AlimTalkResult>;
48
+ private isAlimTalkProvider;
49
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Test Helpers and Utilities
3
+ * 테스트 헬퍼 및 유틸리티 함수들
4
+ */
5
+ import type { StandardRequest } from "@k-msg/core";
6
+ import type { IWINVConfig } from "./iwinv/types/iwinv";
7
+ export declare const TEST_CONFIGS: {
8
+ development: IWINVConfig;
9
+ production: IWINVConfig;
10
+ invalid: IWINVConfig;
11
+ };
12
+ export declare const createTestRequests: () => {
13
+ alimtalk: {
14
+ welcome: StandardRequest;
15
+ otp: StandardRequest;
16
+ order: StandardRequest;
17
+ };
18
+ sms: {
19
+ short: StandardRequest;
20
+ long: StandardRequest;
21
+ };
22
+ invalid: {
23
+ emptyPhone: StandardRequest;
24
+ invalidPhone: StandardRequest;
25
+ emptyTemplate: StandardRequest;
26
+ };
27
+ };
28
+ export declare const createBulkTestData: (count?: number) => {
29
+ templateCode: string;
30
+ phoneNumber: string;
31
+ variables: {
32
+ index: string;
33
+ name: string;
34
+ message: string;
35
+ };
36
+ channel: "alimtalk" | "sms" | "auto";
37
+ }[];
38
+ export declare const createPerformanceTracker: () => {
39
+ start: () => void;
40
+ end: () => void;
41
+ record: (success: boolean) => void;
42
+ getMetrics: () => {
43
+ startTime: number;
44
+ endTime: number;
45
+ duration: number;
46
+ memoryUsage: {
47
+ start: number;
48
+ end: number;
49
+ peak: number;
50
+ };
51
+ requestCount: number;
52
+ successCount: number;
53
+ errorCount: number;
54
+ };
55
+ reset: () => void;
56
+ };
57
+ export declare const createMockHttpResponse: (options?: {
58
+ success?: boolean;
59
+ delay?: number;
60
+ statusCode?: number;
61
+ data?: any;
62
+ }) => Promise<unknown>;
63
+ export declare const createConcurrencyTester: () => {
64
+ runConcurrent: <T>(operations: (() => Promise<T>)[], maxConcurrency?: number) => Promise<Array<{
65
+ result: T | null;
66
+ error: Error | null;
67
+ duration: number;
68
+ }>>;
69
+ testRateLimit: <T>(operation: () => Promise<T>, requestsPerSecond: number, duration: number) => Promise<{
70
+ attempted: number;
71
+ successful: number;
72
+ failed: number;
73
+ actualRate: number;
74
+ }>;
75
+ };
76
+ export declare const createValidationHelpers: () => {
77
+ isValidPhoneNumber: (phone: string) => boolean;
78
+ isValidTemplateCode: (code: string) => boolean;
79
+ containsSensitiveData: (variables: Record<string, string>) => boolean;
80
+ getMessageType: (message: string) => "sms" | "lms" | "mms";
81
+ };
82
+ export declare const createTestStateTracker: () => {
83
+ recordTest: (name: string, passed: boolean, duration: number, error?: string) => void;
84
+ skip: (name: string) => void;
85
+ getStats: () => {
86
+ totalTests: number;
87
+ passedTests: number;
88
+ failedTests: number;
89
+ skippedTests: number;
90
+ duration: number;
91
+ errors: Array<{
92
+ test: string;
93
+ error: string;
94
+ }>;
95
+ };
96
+ getSummary: () => {
97
+ successRate: number;
98
+ averageDuration: number;
99
+ totalTests: number;
100
+ passedTests: number;
101
+ failedTests: number;
102
+ skippedTests: number;
103
+ duration: number;
104
+ errors: Array<{
105
+ test: string;
106
+ error: string;
107
+ }>;
108
+ };
109
+ reset: () => void;
110
+ };
@@ -0,0 +1,69 @@
1
+ export interface AligoConfig {
2
+ apiKey: string;
3
+ userId: string;
4
+ senderKey?: string;
5
+ sender?: string;
6
+ testMode?: boolean;
7
+ debug?: boolean;
8
+ smsBaseUrl?: string;
9
+ alimtalkBaseUrl?: string;
10
+ friendtalkEndpoint?: string;
11
+ }
12
+ export interface AligoSMSRequest {
13
+ key: string;
14
+ user_id: string;
15
+ sender: string;
16
+ receiver: string;
17
+ msg: string;
18
+ msg_type?: "SMS" | "LMS" | "MMS";
19
+ title?: string;
20
+ testmode_yn?: "Y" | "N";
21
+ destination?: string;
22
+ rdate?: string;
23
+ rtime?: string;
24
+ image?: string;
25
+ }
26
+ export interface AligoAlimTalkRequest {
27
+ apikey: string;
28
+ userid: string;
29
+ senderkey: string;
30
+ tpl_code: string;
31
+ sender: string;
32
+ [key: string]: any;
33
+ testMode?: "Y" | "N";
34
+ }
35
+ export interface AligoResponse {
36
+ result_code: string;
37
+ message: string;
38
+ msg_id?: string;
39
+ success_cnt?: number;
40
+ error_cnt?: number;
41
+ msg_type?: string;
42
+ }
43
+ export interface AligoTemplateListRequest {
44
+ apikey: string;
45
+ userid: string;
46
+ senderkey: string;
47
+ tpl_code?: string;
48
+ }
49
+ export interface AligoTemplateCreateRequest {
50
+ apikey: string;
51
+ userid: string;
52
+ senderkey: string;
53
+ tpl_name: string;
54
+ tpl_content: string;
55
+ tpl_button?: string;
56
+ }
57
+ export interface AligoTemplateDeleteRequest {
58
+ apikey: string;
59
+ userid: string;
60
+ senderkey: string;
61
+ tpl_code: string;
62
+ }
63
+ export interface AligoRemainResponse {
64
+ result_code: string;
65
+ message: string;
66
+ SMS_CNT: number;
67
+ LMS_CNT: number;
68
+ MMS_CNT: number;
69
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * 공통 프로바이더 인터페이스와 타입 정의
3
+ * 모든 K-Message 프로바이더가 구현해야 하는 기본 인터페이스
4
+ * 알림톡, 친구톡, SMS, LMS 등 다양한 메시징 채널 지원
5
+ */
6
+ export declare enum MessageChannel {
7
+ ALIMTALK = "alimtalk",// 카카오 알림톡
8
+ FRIENDTALK = "friendtalk",// 카카오 친구톡
9
+ SMS = "sms",// 단문 메시지
10
+ LMS = "lms",// 장문 메시지
11
+ MMS = "mms",// 멀티미디어 메시지
12
+ PUSH = "push",// 푸시 알림
13
+ EMAIL = "email"
14
+ }
15
+ export declare enum MessageType {
16
+ TEXT = "text",// 텍스트만
17
+ RICH = "rich",// 리치 메시지 (버튼, 이미지 등)
18
+ TEMPLATE = "template",// 템플릿 기반
19
+ CUSTOM = "custom"
20
+ }
21
+ export interface SendOptions {
22
+ channel?: MessageChannel;
23
+ messageType?: MessageType;
24
+ reserve?: boolean;
25
+ sendDate?: Date | string;
26
+ timezone?: string;
27
+ senderKey?: string;
28
+ senderNumber?: string;
29
+ senderName?: string;
30
+ enableFallback?: boolean;
31
+ fallbackChannel?: MessageChannel;
32
+ fallbackContent?: string;
33
+ fallbackTitle?: string;
34
+ title?: string;
35
+ subject?: string;
36
+ priority?: "high" | "normal" | "low";
37
+ trackingId?: string;
38
+ campaignId?: string;
39
+ tags?: string[];
40
+ attachments?: MediaAttachment[];
41
+ metadata?: Record<string, any>;
42
+ }
43
+ export interface MediaAttachment {
44
+ type: "image" | "video" | "audio" | "document";
45
+ url: string;
46
+ filename?: string;
47
+ size?: number;
48
+ mimeType?: string;
49
+ }
50
+ export interface TemplateFilters {
51
+ templateCode?: string;
52
+ templateName?: string;
53
+ templateStatus?: string;
54
+ [key: string]: any;
55
+ }
56
+ export interface HistoryFilters {
57
+ reserve?: "Y" | "N" | boolean;
58
+ startDate?: string | Date;
59
+ endDate?: string | Date;
60
+ messageId?: number | string;
61
+ phone?: string;
62
+ [key: string]: any;
63
+ }
64
+ export interface HealthCheckResult {
65
+ healthy: boolean;
66
+ issues: string[];
67
+ data?: {
68
+ balance?: number;
69
+ status: string;
70
+ code?: number;
71
+ message?: string;
72
+ } | null;
73
+ }
74
+ export interface SendResult {
75
+ success: boolean;
76
+ messageId: string | null;
77
+ status: string;
78
+ error: string | null;
79
+ }
80
+ export interface TemplateResult {
81
+ success: boolean;
82
+ templateCode: string | null;
83
+ status: string;
84
+ error: string | null;
85
+ }
86
+ export interface BaseProvider<TConfig = any> {
87
+ readonly id: string;
88
+ readonly name: string;
89
+ readonly supportedChannels: MessageChannel[];
90
+ readonly supportedTypes: MessageType[];
91
+ healthCheck(): Promise<HealthCheckResult>;
92
+ sendMessage?(recipient: string, // 수신자 (전화번호 또는 이메일)
93
+ content: MessageContent, options?: SendOptions): Promise<SendResult>;
94
+ sendTemplateMessage?(templateCode: string, phoneNumber: string, variables: Record<string, any>, options?: SendOptions): Promise<SendResult>;
95
+ createTemplate?(template: TemplateCreateRequest): Promise<TemplateResult>;
96
+ getTemplates?(pageNum?: number, pageSize?: number, filters?: TemplateFilters): Promise<any>;
97
+ modifyTemplate?(templateCode: string, template: TemplateUpdateRequest): Promise<TemplateResult>;
98
+ deleteTemplate?(templateCode: string): Promise<any>;
99
+ getHistory?(pageNum?: number, pageSize?: number, filters?: HistoryFilters): Promise<any>;
100
+ cancelReservation?(messageId: number | string): Promise<any>;
101
+ getSenderNumbers?(): Promise<SenderNumber[]>;
102
+ verifySenderNumber?(phoneNumber: string): Promise<SenderVerificationResult>;
103
+ getChannelInfo?(channel: MessageChannel): Promise<ChannelInfo>;
104
+ }
105
+ export interface MessageContent {
106
+ channel?: MessageChannel;
107
+ type?: MessageType;
108
+ text: string;
109
+ title?: string;
110
+ templateId?: string;
111
+ variables?: Record<string, any>;
112
+ buttons?: MessageButton[];
113
+ attachments?: MediaAttachment[];
114
+ }
115
+ export interface MessageButton {
116
+ type: "web" | "app" | "phone" | "delivery";
117
+ text: string;
118
+ url?: string;
119
+ scheme?: string;
120
+ phoneNumber?: string;
121
+ }
122
+ export interface TemplateCreateRequest {
123
+ name: string;
124
+ content: string;
125
+ channel: MessageChannel;
126
+ category?: string;
127
+ buttons?: MessageButton[];
128
+ variables?: string[];
129
+ description?: string;
130
+ }
131
+ export interface TemplateUpdateRequest {
132
+ name?: string;
133
+ content?: string;
134
+ buttons?: MessageButton[];
135
+ description?: string;
136
+ }
137
+ export interface SenderNumber {
138
+ phoneNumber: string;
139
+ name?: string;
140
+ verified: boolean;
141
+ verifiedAt?: Date;
142
+ status: "active" | "pending" | "rejected" | "blocked";
143
+ }
144
+ export interface SenderVerificationResult {
145
+ success: boolean;
146
+ phoneNumber: string;
147
+ status: string;
148
+ verificationCode?: string;
149
+ error?: string;
150
+ }
151
+ export interface ChannelInfo {
152
+ channel: MessageChannel;
153
+ available: boolean;
154
+ limits: {
155
+ maxLength?: number;
156
+ maxAttachments?: number;
157
+ maxAttachmentSize?: number;
158
+ };
159
+ features: {
160
+ supportsButtons: boolean;
161
+ supportsAttachments: boolean;
162
+ supportsTemplates: boolean;
163
+ supportsScheduling: boolean;
164
+ };
165
+ }
166
+ export interface BaseProviderConfig {
167
+ apiKey: string;
168
+ baseUrl?: string;
169
+ debug?: boolean;
170
+ timeout?: number;
171
+ retries?: number;
172
+ }