@k-msg/core 0.24.1 → 0.25.0
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.
- package/dist/errors.d.ts +7 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +5 -5
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +5 -5
- package/dist/provider.d.ts +127 -0
- package/dist/result.d.ts +103 -0
- package/dist/types/message.d.ts +63 -0
- package/package.json +1 -1
package/dist/provider.d.ts
CHANGED
|
@@ -1,56 +1,123 @@
|
|
|
1
1
|
import type { KMsgError } from "./errors";
|
|
2
2
|
import type { Result } from "./result";
|
|
3
3
|
import type { BalanceQuery, BalanceResult, DeliveryStatusQuery, DeliveryStatusResult, KakaoChannel, KakaoChannelCategories, MessageType, ProviderOnboardingSpec, SendOptions, SendResult } from "./types/index";
|
|
4
|
+
/**
|
|
5
|
+
* Represents an AlimTalk template registered with a provider.
|
|
6
|
+
* Templates must be approved by Kakao before use.
|
|
7
|
+
*/
|
|
4
8
|
export interface Template {
|
|
9
|
+
/** Unique template identifier. */
|
|
5
10
|
id: string;
|
|
11
|
+
/** Template code used in send requests. */
|
|
6
12
|
code: string;
|
|
13
|
+
/** Human-readable template name. */
|
|
7
14
|
name: string;
|
|
15
|
+
/** Template body with #{variable} placeholders. */
|
|
8
16
|
content: string;
|
|
17
|
+
/** Template category (e.g., "authentication", "promotion"). */
|
|
9
18
|
category?: string;
|
|
19
|
+
/** Approval status of the template. */
|
|
10
20
|
status: "APPROVED" | "REJECTED" | "PENDING" | "INSPECTION";
|
|
21
|
+
/** Button configurations attached to the template. */
|
|
11
22
|
buttons?: unknown[];
|
|
23
|
+
/** Names of variables expected in the template content. */
|
|
12
24
|
variables?: string[];
|
|
25
|
+
/** When the template was created. */
|
|
13
26
|
createdAt: Date;
|
|
27
|
+
/** When the template was last updated. */
|
|
14
28
|
updatedAt: Date;
|
|
15
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Input for creating a new AlimTalk template.
|
|
32
|
+
*/
|
|
16
33
|
export type TemplateCreateInput = {
|
|
34
|
+
/** Human-readable template name. */
|
|
17
35
|
name: string;
|
|
36
|
+
/** Template body with #{variable} placeholders. */
|
|
18
37
|
content: string;
|
|
38
|
+
/** Template category. */
|
|
19
39
|
category?: string;
|
|
40
|
+
/** Button configurations. */
|
|
20
41
|
buttons?: unknown[];
|
|
42
|
+
/** Expected variable names in the template. */
|
|
21
43
|
variables?: string[];
|
|
22
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* Partial input for updating an existing template.
|
|
47
|
+
*/
|
|
23
48
|
export type TemplateUpdateInput = Partial<TemplateCreateInput>;
|
|
49
|
+
/**
|
|
50
|
+
* Context passed to template operations.
|
|
51
|
+
*/
|
|
24
52
|
export type TemplateContext = {
|
|
25
53
|
/**
|
|
26
54
|
* Provider-specific Kakao channel key (e.g. Aligo senderKey).
|
|
27
55
|
*/
|
|
28
56
|
kakaoChannelSenderKey?: string;
|
|
29
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Interface for providers that support AlimTalk template management.
|
|
60
|
+
*/
|
|
30
61
|
export interface TemplateProvider {
|
|
62
|
+
/**
|
|
63
|
+
* Create a new template.
|
|
64
|
+
*/
|
|
31
65
|
createTemplate(input: TemplateCreateInput, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
|
|
66
|
+
/**
|
|
67
|
+
* Update an existing template by code.
|
|
68
|
+
*/
|
|
32
69
|
updateTemplate(code: string, patch: TemplateUpdateInput, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
|
|
70
|
+
/**
|
|
71
|
+
* Delete a template by code.
|
|
72
|
+
*/
|
|
33
73
|
deleteTemplate(code: string, ctx?: TemplateContext): Promise<Result<void, KMsgError>>;
|
|
74
|
+
/**
|
|
75
|
+
* Get a template by code.
|
|
76
|
+
*/
|
|
34
77
|
getTemplate(code: string, ctx?: TemplateContext): Promise<Result<Template, KMsgError>>;
|
|
78
|
+
/**
|
|
79
|
+
* List templates with optional filtering and pagination.
|
|
80
|
+
*/
|
|
35
81
|
listTemplates(params?: {
|
|
36
82
|
status?: string;
|
|
37
83
|
page?: number;
|
|
38
84
|
limit?: number;
|
|
39
85
|
}, ctx?: TemplateContext): Promise<Result<Template[], KMsgError>>;
|
|
40
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Interface for providers that support requesting template inspection.
|
|
89
|
+
*/
|
|
41
90
|
export interface TemplateInspectionProvider {
|
|
91
|
+
/**
|
|
92
|
+
* Request inspection for a template (submits for approval review).
|
|
93
|
+
*/
|
|
42
94
|
requestTemplateInspection(code: string, ctx?: TemplateContext): Promise<Result<void, KMsgError>>;
|
|
43
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Interface for providers that support Kakao channel management.
|
|
98
|
+
*/
|
|
44
99
|
export interface KakaoChannelProvider {
|
|
100
|
+
/**
|
|
101
|
+
* List registered Kakao channels.
|
|
102
|
+
*/
|
|
45
103
|
listKakaoChannels(params?: {
|
|
46
104
|
plusId?: string;
|
|
47
105
|
senderKey?: string;
|
|
48
106
|
}): Promise<Result<KakaoChannel[], KMsgError>>;
|
|
107
|
+
/**
|
|
108
|
+
* List available channel categories for registration.
|
|
109
|
+
*/
|
|
49
110
|
listKakaoChannelCategories?(): Promise<Result<KakaoChannelCategories, KMsgError>>;
|
|
111
|
+
/**
|
|
112
|
+
* Request authentication SMS for channel registration.
|
|
113
|
+
*/
|
|
50
114
|
requestKakaoChannelAuth?(params: {
|
|
51
115
|
plusId: string;
|
|
52
116
|
phoneNumber: string;
|
|
53
117
|
}): Promise<Result<void, KMsgError>>;
|
|
118
|
+
/**
|
|
119
|
+
* Add a Kakao channel after authentication.
|
|
120
|
+
*/
|
|
54
121
|
addKakaoChannel?(params: {
|
|
55
122
|
plusId: string;
|
|
56
123
|
authNum: string;
|
|
@@ -58,21 +125,81 @@ export interface KakaoChannelProvider {
|
|
|
58
125
|
categoryCode: string;
|
|
59
126
|
}): Promise<Result<KakaoChannel, KMsgError>>;
|
|
60
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Health check result from a provider.
|
|
130
|
+
*/
|
|
61
131
|
export interface ProviderHealthStatus {
|
|
132
|
+
/** Whether the provider is operational. */
|
|
62
133
|
healthy: boolean;
|
|
134
|
+
/** List of issues if not healthy. */
|
|
63
135
|
issues: string[];
|
|
136
|
+
/** Response latency in milliseconds. */
|
|
64
137
|
latencyMs?: number;
|
|
138
|
+
/** Provider-specific health details. */
|
|
65
139
|
data?: Record<string, unknown>;
|
|
66
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Interface for providers that support balance queries.
|
|
143
|
+
*/
|
|
67
144
|
export interface BalanceProvider {
|
|
145
|
+
/**
|
|
146
|
+
* Query the remaining balance/points for the provider account.
|
|
147
|
+
*/
|
|
68
148
|
getBalance(query?: BalanceQuery): Promise<Result<BalanceResult, KMsgError>>;
|
|
69
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Core provider interface for sending messages.
|
|
152
|
+
*
|
|
153
|
+
* All providers must implement this interface. Optional capabilities
|
|
154
|
+
* (balance, templates, delivery status) are exposed via separate interfaces.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* class MyProvider implements Provider {
|
|
159
|
+
* readonly id = "my-provider";
|
|
160
|
+
* readonly name = "My Provider";
|
|
161
|
+
* readonly supportedTypes = ["SMS", "LMS"] as const;
|
|
162
|
+
*
|
|
163
|
+
* async healthCheck() { return { healthy: true, issues: [] }; }
|
|
164
|
+
* async send(params) { ... }
|
|
165
|
+
* }
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
70
168
|
export interface Provider {
|
|
169
|
+
/**
|
|
170
|
+
* Unique identifier for this provider instance.
|
|
171
|
+
* Used for routing and logging.
|
|
172
|
+
* @example "solapi"
|
|
173
|
+
*/
|
|
71
174
|
readonly id: string;
|
|
175
|
+
/**
|
|
176
|
+
* Human-readable name for display purposes.
|
|
177
|
+
* @example "SOLAPI"
|
|
178
|
+
*/
|
|
72
179
|
readonly name: string;
|
|
180
|
+
/**
|
|
181
|
+
* Message types this provider supports.
|
|
182
|
+
* Messages of unsupported types will be rejected.
|
|
183
|
+
*/
|
|
73
184
|
readonly supportedTypes: readonly MessageType[];
|
|
185
|
+
/**
|
|
186
|
+
* Check if the provider is operational.
|
|
187
|
+
* Used for health monitoring and circuit breaker decisions.
|
|
188
|
+
*/
|
|
74
189
|
healthCheck(): Promise<ProviderHealthStatus>;
|
|
190
|
+
/**
|
|
191
|
+
* Send a message through this provider.
|
|
192
|
+
* @returns Result with SendResult on success, KMsgError on failure.
|
|
193
|
+
*/
|
|
75
194
|
send(params: SendOptions): Promise<Result<SendResult, KMsgError>>;
|
|
195
|
+
/**
|
|
196
|
+
* Query delivery status for a previously sent message.
|
|
197
|
+
* Optional capability - not all providers support this.
|
|
198
|
+
*/
|
|
76
199
|
getDeliveryStatus?(query: DeliveryStatusQuery): Promise<Result<DeliveryStatusResult | null, KMsgError>>;
|
|
200
|
+
/**
|
|
201
|
+
* Get the onboarding specification for this provider.
|
|
202
|
+
* Used by tooling to guide provider configuration.
|
|
203
|
+
*/
|
|
77
204
|
getOnboardingSpec?(): ProviderOnboardingSpec;
|
|
78
205
|
}
|
package/dist/result.d.ts
CHANGED
|
@@ -1,15 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a successful result containing a value.
|
|
3
|
+
*/
|
|
1
4
|
export type Ok<T> = {
|
|
5
|
+
/** Always true for successful results. */
|
|
2
6
|
readonly isSuccess: true;
|
|
7
|
+
/** Always false for successful results. */
|
|
3
8
|
readonly isFailure: false;
|
|
9
|
+
/** The contained success value. */
|
|
4
10
|
readonly value: T;
|
|
5
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Represents a failed result containing an error.
|
|
14
|
+
*/
|
|
6
15
|
export type Fail<E> = {
|
|
16
|
+
/** Always false for failed results. */
|
|
7
17
|
readonly isSuccess: false;
|
|
18
|
+
/** Always true for failed results. */
|
|
8
19
|
readonly isFailure: true;
|
|
20
|
+
/** The contained error. */
|
|
9
21
|
readonly error: E;
|
|
10
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* A result type that represents either success (Ok) or failure (Fail).
|
|
25
|
+
* Used throughout k-msg for explicit error handling without exceptions.
|
|
26
|
+
*
|
|
27
|
+
* @template T - The type of the success value
|
|
28
|
+
* @template E - The type of the error (defaults to Error)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
33
|
+
* if (b === 0) return fail("division by zero");
|
|
34
|
+
* return ok(a / b);
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* const result = divide(10, 2);
|
|
38
|
+
* if (result.isSuccess) {
|
|
39
|
+
* console.log(result.value); // 5
|
|
40
|
+
* } else {
|
|
41
|
+
* console.error(result.error);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
11
45
|
export type Result<T, E = Error> = Ok<T> | Fail<E>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a successful result containing the given value.
|
|
48
|
+
* @param value - The success value to wrap
|
|
49
|
+
* @returns An Ok result containing the value
|
|
50
|
+
*/
|
|
12
51
|
export declare const ok: <T>(value: T) => Ok<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Create a failed result containing the given error.
|
|
54
|
+
* @param error - The error to wrap
|
|
55
|
+
* @returns A Fail result containing the error
|
|
56
|
+
*/
|
|
13
57
|
export declare const fail: <E>(error: E) => Fail<E>;
|
|
14
58
|
/**
|
|
15
59
|
* Result utility functions for chaining and transformation
|
|
@@ -58,4 +102,63 @@ export declare const Result: {
|
|
|
58
102
|
* Check if a Result is Fail
|
|
59
103
|
*/
|
|
60
104
|
isFail<T, E>(result: Result<T, E>): result is Fail<E>;
|
|
105
|
+
/**
|
|
106
|
+
* Execute a side-effect without breaking the chain.
|
|
107
|
+
* Calls fn with the result (ok or fail) and returns the same result.
|
|
108
|
+
*
|
|
109
|
+
* @param result - The Result to tap
|
|
110
|
+
* @param fn - Side-effect function called with the result
|
|
111
|
+
* @returns The same Result for chaining
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const result = await provider.send(options);
|
|
116
|
+
* Result.tap(result, r => console.log('Completed:', r));
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
tap<T, E>(result: Result<T, E>, fn: (result: Result<T, E>) => void): Result<T, E>;
|
|
120
|
+
/**
|
|
121
|
+
* Execute a side-effect on success only.
|
|
122
|
+
* Calls fn with the value only if result is ok, returns the same result.
|
|
123
|
+
*
|
|
124
|
+
* @param result - The Result to tap
|
|
125
|
+
* @param fn - Side-effect function called with the value on success
|
|
126
|
+
* @returns The same Result for chaining
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* Result.tapOk(result, value => console.log('Success:', value.messageId));
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
tapOk<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;
|
|
134
|
+
/**
|
|
135
|
+
* Execute a side-effect on failure only.
|
|
136
|
+
* Calls fn with the error only if result is fail, returns the same result.
|
|
137
|
+
*
|
|
138
|
+
* @param result - The Result to tap
|
|
139
|
+
* @param fn - Side-effect function called with the error on failure
|
|
140
|
+
* @returns The same Result for chaining
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* Result.tapErr(result, error => console.error('Failed:', error.message));
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;
|
|
148
|
+
/**
|
|
149
|
+
* Return the value on success, or throw with a custom message on failure.
|
|
150
|
+
* Use this when you want to convert a failed Result to an exception.
|
|
151
|
+
*
|
|
152
|
+
* @param result - The Result to expect
|
|
153
|
+
* @param message - Custom error message to use if result is fail
|
|
154
|
+
* @returns The success value
|
|
155
|
+
* @throws Error with the provided message (and original error as cause)
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* const value = Result.expect(result, 'Message send failed');
|
|
160
|
+
* // throws Error('Message send failed') if result is fail
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
expect<T, E>(result: Result<T, E>, message: string): T;
|
|
61
164
|
};
|
package/dist/types/message.d.ts
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported message types in the k-msg platform.
|
|
3
|
+
*
|
|
4
|
+
* - ALIMTALK: Kakao AlimTalk (notification talk) with approved template
|
|
5
|
+
* - FRIENDTALK: Kakao FriendTalk (friend message, no template required)
|
|
6
|
+
* - SMS: Short message (up to 90 bytes, typically ~90 Korean characters)
|
|
7
|
+
* - LMS: Long message with subject line
|
|
8
|
+
* - MMS: Multimedia message with image attachment
|
|
9
|
+
* - NSA: Naver Smart Alarm (notification service)
|
|
10
|
+
* - VOICE: Voice call message
|
|
11
|
+
* - FAX: Fax transmission
|
|
12
|
+
* - RCS_SMS/LMS/MMS: Rich Communication Services text/media messages
|
|
13
|
+
* - RCS_TPL/ITPL/LTPL: RCS template-based messages
|
|
14
|
+
*/
|
|
1
15
|
export type MessageType = "ALIMTALK" | "FRIENDTALK" | "SMS" | "LMS" | "MMS" | "NSA" | "VOICE" | "FAX" | "RCS_SMS" | "RCS_LMS" | "RCS_MMS" | "RCS_TPL" | "RCS_ITPL" | "RCS_LTPL";
|
|
16
|
+
/**
|
|
17
|
+
* Message delivery status.
|
|
18
|
+
*
|
|
19
|
+
* - PENDING: Queued or in transit
|
|
20
|
+
* - SENT: Successfully delivered to the carrier
|
|
21
|
+
* - FAILED: Delivery failed
|
|
22
|
+
*/
|
|
2
23
|
export type MessageStatus = "PENDING" | "SENT" | "FAILED";
|
|
3
24
|
export declare const KNOWN_MESSAGE_STATUSES: MessageStatus[];
|
|
4
25
|
export declare const QUEUED_MESSAGE_STATUS: MessageStatus;
|
|
5
26
|
export declare const normalizeMessageStatus: (status: unknown) => MessageStatus;
|
|
27
|
+
/**
|
|
28
|
+
* Variables for template interpolation.
|
|
29
|
+
* Values are substituted into #{variableName} placeholders in templates.
|
|
30
|
+
* @example { name: "John", code: "123456" }
|
|
31
|
+
*/
|
|
6
32
|
export type MessageVariables = Record<string, string | number | boolean | Date | null | undefined>;
|
|
7
33
|
export interface MessageButton {
|
|
8
34
|
name: string;
|
|
@@ -45,6 +71,10 @@ export interface CommonSendOptions {
|
|
|
45
71
|
* Optional routing hint to force a specific provider by id.
|
|
46
72
|
*/
|
|
47
73
|
providerId?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Recipient phone number in Korean format without hyphens.
|
|
76
|
+
* @example "01012345678"
|
|
77
|
+
*/
|
|
48
78
|
to: string;
|
|
49
79
|
/**
|
|
50
80
|
* Sender number / sender id. Optional at KMsg layer; providers may require it.
|
|
@@ -202,7 +232,15 @@ export interface RcsTemplateSendOptions extends CommonSendOptions {
|
|
|
202
232
|
variables: MessageVariables;
|
|
203
233
|
rcs?: RcsSendOptions;
|
|
204
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Union of all supported send option types.
|
|
237
|
+
* Use this for type narrowing based on the `type` discriminator.
|
|
238
|
+
*/
|
|
205
239
|
export type SendOptions = SmsSendOptions | AlimTalkSendOptions | FriendTalkSendOptions | NsaSendOptions | VoiceMessageSendOptions | FaxMessageSendOptions | RcsTextSendOptions | RcsTemplateSendOptions;
|
|
240
|
+
/**
|
|
241
|
+
* Relaxed SMS input type that allows omitting `type` and using `content` as an alias for `text`.
|
|
242
|
+
* Used for developer convenience when sending simple SMS messages.
|
|
243
|
+
*/
|
|
206
244
|
export type SmsDefaultSendInput = Omit<SmsSendOptions, "type" | "text"> & {
|
|
207
245
|
type?: undefined;
|
|
208
246
|
/**
|
|
@@ -220,16 +258,41 @@ export type SmsDefaultSendInput = Omit<SmsSendOptions, "type" | "text"> & {
|
|
|
220
258
|
* - Other channels are modeled as discriminated unions on `type`.
|
|
221
259
|
*/
|
|
222
260
|
export type SendInput = SendOptions | SmsDefaultSendInput;
|
|
261
|
+
/**
|
|
262
|
+
* Result of a message send operation.
|
|
263
|
+
* Returned by Provider.send() and KMsg.send().
|
|
264
|
+
*/
|
|
223
265
|
export interface SendResult {
|
|
224
266
|
/**
|
|
225
267
|
* Correlation id (equals the request `messageId`).
|
|
226
268
|
*/
|
|
227
269
|
messageId: string;
|
|
270
|
+
/**
|
|
271
|
+
* Identifier of the provider that handled this message.
|
|
272
|
+
*/
|
|
228
273
|
providerId: string;
|
|
274
|
+
/**
|
|
275
|
+
* Provider-specific message identifier for tracking.
|
|
276
|
+
*/
|
|
229
277
|
providerMessageId?: string;
|
|
278
|
+
/**
|
|
279
|
+
* Current delivery status of the message.
|
|
280
|
+
*/
|
|
230
281
|
status: MessageStatus;
|
|
282
|
+
/**
|
|
283
|
+
* The message type that was sent.
|
|
284
|
+
*/
|
|
231
285
|
type: MessageType;
|
|
286
|
+
/**
|
|
287
|
+
* Recipient phone number.
|
|
288
|
+
*/
|
|
232
289
|
to: string;
|
|
290
|
+
/**
|
|
291
|
+
* Non-fatal warnings (e.g., failover partially applied).
|
|
292
|
+
*/
|
|
233
293
|
warnings?: SendWarning[];
|
|
294
|
+
/**
|
|
295
|
+
* Raw provider response for debugging (provider-specific shape).
|
|
296
|
+
*/
|
|
234
297
|
raw?: unknown;
|
|
235
298
|
}
|