k-msg 0.3.0 β 0.5.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/README.md +41 -397
- package/dist/index.d.ts +3 -10
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -5
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +4 -5
- package/package.json +9 -8
- package/dist/modules/index.d.ts +0 -330
package/README.md
CHANGED
|
@@ -1,415 +1,59 @@
|
|
|
1
1
|
# k-msg
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Unified package that re-exports the main public API:
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
- `KMsg` from `@k-msg/messaging`
|
|
6
|
+
- Built-in providers from `@k-msg/provider`
|
|
7
|
+
- Core types/utilities from `@k-msg/core`
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
# Using npm
|
|
13
12
|
npm install k-msg
|
|
14
|
-
|
|
15
|
-
# Using bun (recommended)
|
|
13
|
+
# or
|
|
16
14
|
bun add k-msg
|
|
17
|
-
|
|
18
|
-
# Using yarn
|
|
19
|
-
yarn add k-msg
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Features
|
|
23
|
-
|
|
24
|
-
### π **Core Capabilities**
|
|
25
|
-
- **π’ Multi-Provider Support** - IWINV, Aligo, Kakao Business, NHN KCP
|
|
26
|
-
- **π¬ Rich Messaging** - AlimTalk, FriendTalk, SMS, LMS with media support
|
|
27
|
-
- **π Smart Fallback** - Automatic provider switching and message type fallback
|
|
28
|
-
- **π± Mobile-First** - Optimized for Korean mobile messaging ecosystem
|
|
29
|
-
|
|
30
|
-
### π οΈ **Developer Experience**
|
|
31
|
-
- **π Template Engine** - Dynamic templates with variable substitution (`#{variable}`)
|
|
32
|
-
- **π Type Safety** - Full TypeScript support with strict type checking
|
|
33
|
-
- **π§ͺ Testing Tools** - Built-in test utilities and mock providers
|
|
34
|
-
- **π Rich Documentation** - Comprehensive guides and API references
|
|
35
|
-
|
|
36
|
-
### π **Analytics & Monitoring**
|
|
37
|
-
- **π Real-time Analytics** - Message delivery, open rates, click tracking
|
|
38
|
-
- **π― Smart Insights** - AI-powered optimization recommendations
|
|
39
|
-
- **π¨ Health Monitoring** - Provider health checks and system monitoring
|
|
40
|
-
- **π Custom Reports** - Flexible reporting with CSV/JSON export
|
|
41
|
-
|
|
42
|
-
### β‘ **Performance & Reliability**
|
|
43
|
-
- **π Retry Logic** - Exponential backoff with jitter
|
|
44
|
-
- **π¦ Rate Limiting** - Built-in rate limiting and queue management
|
|
45
|
-
- **πͺ Circuit Breaker** - Automatic failure recovery
|
|
46
|
-
- **π‘ Webhook System** - Real-time event notifications
|
|
47
|
-
|
|
48
|
-
## π Quick Start
|
|
49
|
-
|
|
50
|
-
### Basic Usage with KMsg
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import { KMsg, IWINVProvider, ok, fail } from 'k-msg';
|
|
54
|
-
|
|
55
|
-
// Initialize KMsg with IWINV provider
|
|
56
|
-
const kmsg = new KMsg(new IWINVProvider({
|
|
57
|
-
apiKey: process.env.IWINV_API_KEY!,
|
|
58
|
-
baseUrl: 'https://alimtalk.bizservice.iwinv.kr'
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
// Send an SMS message
|
|
62
|
-
const smsResult = await kmsg.send({
|
|
63
|
-
type: 'SMS',
|
|
64
|
-
to: '01012345678',
|
|
65
|
-
from: '01000000000',
|
|
66
|
-
text: 'Hello #{name}, this is a test SMS!',
|
|
67
|
-
variables: { name: 'νκΈΈλ' }
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (result.isSuccess) {
|
|
71
|
-
console.log('β
Message sent successfully:', result.value.messageId);
|
|
72
|
-
} else {
|
|
73
|
-
console.error('β Failed to send message:', result.error.message);
|
|
74
|
-
}
|
|
75
15
|
```
|
|
76
16
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
import {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
### Template Management
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
import { IWINVAdapter, TemplateService } from 'k-msg';
|
|
110
|
-
|
|
111
|
-
const adapter = new IWINVAdapter(config);
|
|
112
|
-
const templateService = new TemplateService(adapter);
|
|
113
|
-
|
|
114
|
-
// Create a new template
|
|
115
|
-
const template = await templateService.create({
|
|
116
|
-
code: 'order_confirmation',
|
|
117
|
-
name: 'order_confirmation',
|
|
118
|
-
content: 'μ£Όλ¬Έμ΄ μλ£λμμ΅λλ€. μ£Όλ¬Έλ²νΈ: #{orderNumber}',
|
|
119
|
-
category: 'TRANSACTION'
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// List all templates
|
|
123
|
-
const result = await templateService.list();
|
|
124
|
-
if (result.isSuccess) {
|
|
125
|
-
console.log('Available templates:', result.value.length);
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Error Handling with Result Pattern
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
import { KMsg, ok, fail } from 'k-msg';
|
|
133
|
-
|
|
134
|
-
const result = await kmsg.send({
|
|
135
|
-
type: 'ALIMTALK',
|
|
136
|
-
to: '01012345678',
|
|
137
|
-
templateId: 'template_name',
|
|
138
|
-
variables: {}
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
if (result.isFailure) {
|
|
142
|
-
// Handle failure
|
|
143
|
-
const error = result.error;
|
|
144
|
-
console.error('Send failed:', error.message);
|
|
145
|
-
|
|
146
|
-
// You can check error codes or types
|
|
147
|
-
if (error.message.includes('template not found')) {
|
|
148
|
-
// Handle specific error
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
// Handle success
|
|
152
|
-
const { messageId, status } = result.value;
|
|
153
|
-
console.log(`Success: ${messageId} (${status})`);
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## Template Management
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
// Create template
|
|
161
|
-
const templates = await platform.templates();
|
|
162
|
-
const newTemplate = await templates.create(
|
|
163
|
-
'welcome_message',
|
|
164
|
-
'Welcome #{name}! Your account is ready.',
|
|
165
|
-
'GENERAL'
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
// List templates
|
|
169
|
-
const templateList = await templates.list(1, 20);
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## Analytics & Monitoring
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
import { AnalyticsService, InsightEngine } from 'k-message';
|
|
176
|
-
|
|
177
|
-
const analytics = new AnalyticsService();
|
|
178
|
-
|
|
179
|
-
// Get delivery metrics
|
|
180
|
-
const metrics = await analytics.getDeliveryMetrics({
|
|
181
|
-
timeRange: '24h',
|
|
182
|
-
provider: 'iwinv'
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Generate insights
|
|
186
|
-
const insights = new InsightEngine();
|
|
187
|
-
const recommendations = await insights.generateInsights(metrics);
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## Webhook Integration
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
import { WebhookManager } from 'k-message';
|
|
194
|
-
|
|
195
|
-
const webhookManager = new WebhookManager();
|
|
196
|
-
|
|
197
|
-
// Register webhook endpoint
|
|
198
|
-
await webhookManager.registerEndpoint({
|
|
199
|
-
url: 'https://your-app.com/webhook',
|
|
200
|
-
events: ['MESSAGE_SENT', 'MESSAGE_DELIVERED', 'MESSAGE_FAILED'],
|
|
201
|
-
secret: 'your-webhook-secret'
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## π¦ Package Architecture
|
|
206
|
-
|
|
207
|
-
k-msg is built as a modular monorepo. You can install the complete package or individual components:
|
|
208
|
-
|
|
209
|
-
### Complete Package (Recommended)
|
|
210
|
-
```bash
|
|
211
|
-
bun add k-msg # Includes all packages
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Individual Packages
|
|
215
|
-
|
|
216
|
-
| Package | Description | Usage |
|
|
217
|
-
|---------|-------------|-------|
|
|
218
|
-
| `@k-msg/core` | Foundation (types, errors, retry) | Base types and error handling |
|
|
219
|
-
| `@k-msg/provider` | Provider system (IWINV, etc.) | Multi-provider abstraction |
|
|
220
|
-
| `@k-msg/messaging` | Message sending & queues | Core messaging functionality |
|
|
221
|
-
| `@k-msg/template` | Template parsing & management | Dynamic template system |
|
|
222
|
-
| `@k-msg/analytics` | Metrics & reporting | Performance analytics |
|
|
223
|
-
| `@k-msg/webhook` | Event notifications | Real-time webhooks |
|
|
224
|
-
| `@k-msg/channel` | Channel & sender management | Business verification |
|
|
225
|
-
|
|
226
|
-
### Dependency Graph
|
|
227
|
-
```
|
|
228
|
-
core (foundation)
|
|
229
|
-
βββ provider β core
|
|
230
|
-
βββ template β core
|
|
231
|
-
βββ messaging β core, provider, template
|
|
232
|
-
βββ analytics β core, messaging
|
|
233
|
-
βββ webhook β core, messaging
|
|
234
|
-
βββ channel β core
|
|
235
|
-
βββ k-msg β all packages
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
## βοΈ Configuration
|
|
239
|
-
|
|
240
|
-
### Environment Variables
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
# Required
|
|
244
|
-
IWINV_API_KEY=your-iwinv-api-key
|
|
245
|
-
|
|
246
|
-
# Optional
|
|
247
|
-
IWINV_BASE_URL=https://alimtalk.bizservice.iwinv.kr
|
|
248
|
-
NODE_ENV=development
|
|
249
|
-
PORT=3000
|
|
250
|
-
|
|
251
|
-
# Debug mode
|
|
252
|
-
DEBUG=k-msg:*
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### TypeScript Configuration
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
interface MessageServiceConfig {
|
|
259
|
-
apiKey: string;
|
|
260
|
-
baseUrl?: string;
|
|
261
|
-
debug?: boolean;
|
|
262
|
-
autoLoad?: boolean;
|
|
263
|
-
timeout?: number;
|
|
264
|
-
retryAttempts?: number;
|
|
265
|
-
|
|
266
|
-
// Advanced options
|
|
267
|
-
customHandlers?: {
|
|
268
|
-
templateLoader?: (provider: Provider) => Promise<Template[]>;
|
|
269
|
-
errorHandler?: (error: Error, context: string) => void;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
// Provider-specific settings
|
|
273
|
-
providerSpecific?: {
|
|
274
|
-
iwinv?: {
|
|
275
|
-
templateCategories?: string[];
|
|
276
|
-
maxVariables?: number;
|
|
277
|
-
enableBulkSending?: boolean;
|
|
278
|
-
};
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### Factory Configuration Options
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
// Simple configuration
|
|
287
|
-
const service1 = MessageServiceFactory.createIWINVService({
|
|
288
|
-
apiKey: 'your-key',
|
|
289
|
-
debug: true
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Advanced configuration
|
|
293
|
-
const service2 = MessageServiceFactory.createService(provider, {
|
|
294
|
-
debug: true,
|
|
295
|
-
autoLoad: false,
|
|
296
|
-
customHandlers: {
|
|
297
|
-
errorHandler: (error, context) => {
|
|
298
|
-
console.error(`[${context}] ${error.message}`);
|
|
299
|
-
// Send to monitoring service
|
|
300
|
-
}
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { IWINVProvider, KMsg, SolapiProvider } from "k-msg";
|
|
21
|
+
|
|
22
|
+
const kmsg = new KMsg({
|
|
23
|
+
providers: [
|
|
24
|
+
new SolapiProvider({
|
|
25
|
+
apiKey: process.env.SOLAPI_API_KEY!,
|
|
26
|
+
apiSecret: process.env.SOLAPI_API_SECRET!,
|
|
27
|
+
defaultFrom: "01000000000",
|
|
28
|
+
}),
|
|
29
|
+
new IWINVProvider({
|
|
30
|
+
apiKey: process.env.IWINV_API_KEY!,
|
|
31
|
+
baseUrl: "https://alimtalk.bizservice.iwinv.kr",
|
|
32
|
+
smsApiKey: process.env.IWINV_SMS_API_KEY,
|
|
33
|
+
smsAuthKey: process.env.IWINV_SMS_AUTH_KEY,
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
routing: {
|
|
37
|
+
defaultProviderId: "solapi",
|
|
38
|
+
byType: {
|
|
39
|
+
ALIMTALK: "iwinv",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaults: {
|
|
43
|
+
from: "01000000000",
|
|
44
|
+
sms: { autoLmsBytes: 90 },
|
|
301
45
|
},
|
|
302
|
-
providerSpecific: {
|
|
303
|
-
iwinv: {
|
|
304
|
-
templateCategories: ['AUTHENTICATION', 'NOTIFICATION'],
|
|
305
|
-
enableBulkSending: false
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
## π§ͺ Testing
|
|
312
|
-
|
|
313
|
-
```typescript
|
|
314
|
-
import { MessageServiceFactory, TestUtils } from 'k-msg';
|
|
315
|
-
|
|
316
|
-
// Create test service with mock provider
|
|
317
|
-
const testService = MessageServiceFactory.createIWINVService({
|
|
318
|
-
apiKey: 'test-key',
|
|
319
|
-
debug: true
|
|
320
46
|
});
|
|
321
47
|
|
|
322
|
-
//
|
|
323
|
-
|
|
324
|
-
'01012345678',
|
|
325
|
-
'test_template',
|
|
326
|
-
{ name: 'ν
μ€νΈ μ¬μ©μ' }
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
// Use test utilities
|
|
330
|
-
const testMessage = TestUtils.createTestMessage({
|
|
331
|
-
templateCode: 'AUTH_OTP',
|
|
332
|
-
phoneNumber: '01012345678'
|
|
333
|
-
});
|
|
48
|
+
// Default SMS (type omitted)
|
|
49
|
+
await kmsg.send({ to: "01012345678", text: "hello" });
|
|
334
50
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
51
|
+
// AlimTalk
|
|
52
|
+
await kmsg.send({
|
|
53
|
+
type: "ALIMTALK",
|
|
54
|
+
to: "01012345678",
|
|
55
|
+
templateCode: "AUTH_OTP",
|
|
56
|
+
variables: { code: "123456" },
|
|
338
57
|
});
|
|
339
58
|
```
|
|
340
59
|
|
|
341
|
-
### Run Tests
|
|
342
|
-
|
|
343
|
-
```bash
|
|
344
|
-
# Run all tests
|
|
345
|
-
bun test
|
|
346
|
-
|
|
347
|
-
# Run tests with coverage
|
|
348
|
-
bun test --coverage
|
|
349
|
-
|
|
350
|
-
# Run specific package tests
|
|
351
|
-
bun test packages/core
|
|
352
|
-
bun test packages/messaging
|
|
353
|
-
|
|
354
|
-
# Run tests by type
|
|
355
|
-
bun test:unit # Fast unit tests
|
|
356
|
-
bun test:integration # Integration tests
|
|
357
|
-
bun test:e2e # End-to-end tests (requires real API keys)
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
## π Examples
|
|
361
|
-
|
|
362
|
-
Check out the `/examples` directory for complete working examples:
|
|
363
|
-
|
|
364
|
-
- **Basic Usage** - Simple message sending
|
|
365
|
-
- **Web Server** - Hono/Express integration
|
|
366
|
-
- **Bulk Messaging** - Batch message processing
|
|
367
|
-
- **Template Management** - Dynamic template creation
|
|
368
|
-
- **Analytics Dashboard** - Real-time monitoring
|
|
369
|
-
- **Webhook Integration** - Event-driven architecture
|
|
370
|
-
|
|
371
|
-
## π€ Contributing
|
|
372
|
-
|
|
373
|
-
We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
|
|
374
|
-
|
|
375
|
-
### Development Setup
|
|
376
|
-
|
|
377
|
-
```bash
|
|
378
|
-
# Clone the repository
|
|
379
|
-
git clone https://github.com/k-otp/k-msg.git
|
|
380
|
-
cd k-msg
|
|
381
|
-
|
|
382
|
-
# Install dependencies
|
|
383
|
-
bun install
|
|
384
|
-
|
|
385
|
-
# Build all packages
|
|
386
|
-
bun run build:all
|
|
387
|
-
|
|
388
|
-
# Run tests
|
|
389
|
-
bun test
|
|
390
|
-
|
|
391
|
-
# Start development server
|
|
392
|
-
bun run dev
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
## π License
|
|
396
|
-
|
|
397
|
-
MIT License - see [LICENSE](../../LICENSE) for details.
|
|
398
|
-
|
|
399
|
-
## π Support
|
|
400
|
-
|
|
401
|
-
- **Documentation**: [GitHub Wiki](https://github.com/k-otp/k-msg/wiki)
|
|
402
|
-
- **API Reference**: [TypeDoc](https://k-otp.github.io/k-msg/)
|
|
403
|
-
- **Issues**: [GitHub Issues](https://github.com/k-otp/k-msg/issues)
|
|
404
|
-
- **Discussions**: [GitHub Discussions](https://github.com/k-otp/k-msg/discussions)
|
|
405
|
-
- **Discord**: [Join our Discord](https://discord.gg/k-msg)
|
|
406
|
-
|
|
407
|
-
### Commercial Support
|
|
408
|
-
|
|
409
|
-
For enterprise support, consulting, or custom integrations, please contact us at [support@k-msg.dev](mailto:support@k-msg.dev).
|
|
410
|
-
|
|
411
|
-
---
|
|
412
|
-
|
|
413
|
-
**Made with β€οΈ for the Korean developer community**
|
|
414
|
-
|
|
415
|
-
*K-Message is not affiliated with Kakao Corp or any messaging service providers.*
|
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,7 @@
|
|
|
2
2
|
* K-Message: Korean Multi-Channel Messaging Platform
|
|
3
3
|
* Unified package that re-exports core functionality for easy use
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
5
|
+
export * from "@k-msg/core";
|
|
6
6
|
export { KMsg } from "@k-msg/messaging";
|
|
7
|
-
export
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
/** @deprecated Use KMsg instead */
|
|
11
|
-
createKMsgAnalytics,
|
|
12
|
-
/** @deprecated Use KMsg instead */
|
|
13
|
-
createKMsgSender,
|
|
14
|
-
/** @deprecated Use KMsg instead */
|
|
15
|
-
createKMsgTemplates, } from "./modules";
|
|
7
|
+
export { AligoProvider, IWINVProvider, MockProvider, SolapiProvider } from "@k-msg/provider";
|
|
8
|
+
export type { AligoConfig, IWINVConfig, SolapiConfig } from "@k-msg/provider";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var{defineProperty:
|
|
1
|
+
var{defineProperty:f,getOwnPropertyNames:n,getOwnPropertyDescriptor:d}=Object,p=Object.prototype.hasOwnProperty,g=(e,o,i)=>{for(let r of n(o))if(!p.call(e,r)&&r!=="default")f(e,r,{get:()=>o[r],enumerable:!0});if(i){for(let r of n(o))if(!p.call(i,r)&&r!=="default")f(i,r,{get:()=>o[r],enumerable:!0});return i}};var s=new WeakMap,m=(e)=>{var o=s.get(e),i;if(o)return o;if(o=f({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")n(e).map((r)=>!p.call(o,r)&&f(o,r,{get:()=>e[r],enumerable:!(i=d(e,r))||i.enumerable}));return s.set(e,o),o};var v=(e,o)=>{for(var i in o)f(e,i,{get:o[i],enumerable:!0,configurable:!0,set:(r)=>o[i]=()=>r})};var t={};v(t,{SolapiProvider:()=>a.SolapiProvider,MockProvider:()=>a.MockProvider,KMsg:()=>l.KMsg,IWINVProvider:()=>a.IWINVProvider,AligoProvider:()=>a.AligoProvider});module.exports=m(t);g(t,require("@k-msg/core"),module.exports);var l=require("@k-msg/messaging"),a=require("@k-msg/provider");
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=7F66C101C1AC512E64756E2164756E21
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts"
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * K-Message: Korean Multi-Channel Messaging Platform\n * Unified package that re-exports core functionality for easy use\n */\n\
|
|
6
|
-
"import { IWINVProvider } from \"@k-msg/provider\";\n\n/**\n * Simple message sender for CLI/scripts\n *\n * @example\n * ```typescript\n * import { createKMsgSender } from 'k-msg/modules';\n *\n * const sender = createKMsgSender({\n * iwinvApiKey: process.env.IWINV_API_KEY!\n * });\n *\n * // User defines their own templates and variables\n * await sender.sendMessage('01012345678', 'USER_OTP_TEMPLATE', {\n * code: '123456',\n * serviceName: 'MyApp',\n * expireMinutes: 3\n * });\n * ```\n */\nexport function createKMsgSender(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Send message with custom template and variables\n * User defines their own template structure\n */\n async sendMessage(\n phoneNumber: string,\n templateCode: string,\n variables: Record<string, any>,\n ) {\n try {\n const result = (await provider.send({\n templateCode: templateCode as any,\n phoneNumber,\n variables,\n } as any)) as any;\n\n if (!result.isSuccess) {\n // Handle provider-level failure (e.g., invalid template, etc.)\n const error = result.error;\n const errorMessage =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : \"Provider reported a failure\";\n throw new Error(errorMessage);\n }\n\n const data = result.value;\n\n return {\n messageId: data.messageId,\n status: \"SENT\" as const,\n templateCode,\n phoneNumber,\n variables,\n error: null,\n sentAt: new Date().toISOString(),\n };\n } catch (error) {\n return {\n messageId: null,\n status: \"FAILED\" as const,\n templateCode,\n phoneNumber,\n variables,\n error: error instanceof Error ? error.message : \"Unknown error\",\n sentAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * Send bulk messages with user-defined template\n */\n async sendBulk(\n recipients: Array<{\n phoneNumber: string;\n variables: Record<string, any>;\n }>,\n templateCode: string,\n options?: {\n batchSize?: number;\n batchDelay?: number;\n },\n ) {\n const batchId = `batch_${Date.now()}`;\n const batchSize = options?.batchSize || 10;\n const batchDelay = options?.batchDelay || 1000;\n\n const results = [];\n let successCount = 0;\n let failureCount = 0;\n\n // Process recipients in batches\n for (let i = 0; i < recipients.length; i += batchSize) {\n const batch = recipients.slice(i, i + batchSize);\n\n // Process batch concurrently\n const batchPromises = batch.map(async (recipient) => {\n try {\n const result = (await provider.send({\n templateCode: templateCode as any,\n phoneNumber: recipient.phoneNumber,\n variables: recipient.variables,\n } as any)) as any;\n\n if (result.isSuccess && result.value.messageId) {\n successCount++;\n return {\n messageId: result.value.messageId,\n phoneNumber: recipient.phoneNumber,\n status: \"SENT\" as const,\n variables: recipient.variables,\n error: null,\n };\n } else {\n failureCount++;\n return {\n messageId: null,\n phoneNumber: recipient.phoneNumber,\n status: \"FAILED\" as const,\n variables: recipient.variables,\n error: result.error?.message || \"Unknown error\",\n };\n }\n } catch (error) {\n failureCount++;\n return {\n messageId: null,\n phoneNumber: recipient.phoneNumber,\n status: \"FAILED\" as const,\n variables: recipient.variables,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n });\n\n const batchResults = await Promise.all(batchPromises);\n results.push(...batchResults);\n\n // Add delay between batches (except for the last batch)\n if (i + batchSize < recipients.length && batchDelay > 0) {\n await new Promise((resolve) => setTimeout(resolve, batchDelay));\n }\n }\n\n return {\n batchId,\n templateCode,\n totalCount: recipients.length,\n successCount,\n failureCount,\n processedAt: new Date().toISOString(),\n results,\n };\n },\n\n /**\n * Check message delivery status\n */\n async getStatus(messageId: string) {\n try {\n const status = (await (provider as any).getStatus(messageId)) as any;\n\n return {\n messageId,\n status: status,\n checkedAt: new Date().toISOString(),\n deliveredAt:\n status === \"DELIVERED\" ? new Date().toISOString() : undefined,\n failedAt: status === \"FAILED\" ? new Date().toISOString() : undefined,\n };\n } catch (error) {\n return {\n messageId,\n status: \"UNKNOWN\",\n error:\n error instanceof Error ? error.message : \"Failed to check status\",\n checkedAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * Get platform instance for advanced usage (when implemented)\n */\n // getPlatform: () => platform\n };\n}\n\n/**\n * Template manager for CLI/scripts\n *\n * @example\n * ```typescript\n * const templates = createKMsgTemplates({ ... });\n * await templates.create('user_welcome', 'Welcome #{name}! Your account #{accountId} is ready.');\n * ```\n */\nexport function createKMsgTemplates(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Create template with user-defined structure\n */\n async create(templateCode: string, content: string, description: string) {\n try {\n // Parse variables from template content\n const variables = this.parseVariables(content);\n\n // TODO: Implement createTemplate when available\n const result = {\n templateId: templateCode,\n status: \"pending\",\n message: \"Template creation not implemented yet\",\n };\n\n return {\n id: result.templateId,\n code: result.templateId,\n content,\n description,\n variables,\n status: result.status,\n message: result.message,\n createdAt: new Date().toISOString(),\n };\n } catch (error) {\n return {\n id: null,\n code: templateCode,\n content,\n description,\n variables: this.parseVariables(content),\n status: \"FAILED\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n createdAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * List user templates\n */\n async list(filters?: { status?: string }) {\n try {\n // TODO: Implement templates.list when available\n return [];\n } catch (error) {\n console.warn(\"Failed to list templates:\", error);\n return [];\n }\n },\n\n /**\n * Validate template syntax and extract variables\n */\n async validate(content: string) {\n const variables = this.parseVariables(content);\n const errors: string[] = [];\n\n // Basic validation\n if (content.length === 0) {\n errors.push(\"Template content cannot be empty\");\n }\n\n if (content.length > 1000) {\n errors.push(\"Template content too long (max 1000 chars)\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n variables,\n };\n },\n\n /**\n * Parse variables from template content\n */\n parseVariables(content: string) {\n const matches = content.match(/#{([^}]+)}/g) || [];\n // Use a Set to efficiently get unique variable names\n const uniqueNames = new Set(matches.map((match) => match.slice(2, -1)));\n\n return Array.from(uniqueNames).map((name) => ({\n name,\n type: \"string\",\n required: true,\n }));\n },\n\n /**\n * Test template with sample variables\n */\n async test(templateCode: string, sampleVariables: Record<string, any>) {\n try {\n // TODO: Implement template validation when available\n const template = {\n code: templateCode,\n content: `Template ${templateCode}`,\n variables: [],\n };\n\n // Parse variables from template content\n const requiredVariables = this.parseVariables(template.content);\n const missingVariables = requiredVariables\n .filter((v) => v.required && !(v.name in sampleVariables))\n .map((v) => v.name);\n\n if (missingVariables.length > 0) {\n return {\n templateCode,\n renderedContent: null,\n isValid: false,\n errors: [\n `Missing required variables: ${missingVariables.join(\", \")}`,\n ],\n };\n }\n\n // Render template with sample variables\n let renderedContent = template.content;\n for (const [key, value] of Object.entries(sampleVariables)) {\n const regex = new RegExp(`#{${key}}`, \"g\");\n renderedContent = renderedContent.replace(regex, String(value));\n }\n\n // Check for unreplaced variables\n const unreplacedVars = renderedContent.match(/#{([^}]+)}/g);\n const warnings = unreplacedVars\n ? [`Unreplaced variables found: ${unreplacedVars.join(\", \")}`]\n : [];\n\n return {\n templateCode,\n renderedContent,\n isValid: !unreplacedVars,\n warnings,\n };\n } catch (error) {\n return {\n templateCode,\n renderedContent: null,\n isValid: false,\n error:\n error instanceof Error ? error.message : \"Template test failed\",\n };\n }\n },\n };\n}\n\n/**\n * Analytics reader for scripts/reporting\n */\nexport function createKMsgAnalytics(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Get message statistics for specified period\n */\n async getMessageStats(period: \"day\" | \"week\" | \"month\" = \"day\") {\n try {\n const now = new Date();\n const periodStart = new Date();\n\n switch (period) {\n case \"day\":\n periodStart.setDate(now.getDate() - 1);\n break;\n case \"week\":\n periodStart.setDate(now.getDate() - 7);\n break;\n case \"month\":\n periodStart.setMonth(now.getMonth() - 1);\n break;\n }\n\n // TODO: Implement analytics when available\n const usage = {\n sentMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveredMessages: 0,\n deliveryRate: 0,\n breakdown: { byTemplate: {}, byDay: {}, byHour: {} },\n };\n\n return {\n period,\n totalSent: usage.sentMessages,\n totalDelivered: usage.deliveredMessages,\n totalFailed: usage.failedMessages,\n deliveryRate: usage.deliveryRate,\n periodStart: periodStart.toISOString(),\n periodEnd: now.toISOString(),\n breakdown: usage.breakdown,\n };\n } catch (error) {\n console.warn(\"Failed to get message stats:\", error);\n return {\n period,\n totalSent: 0,\n totalDelivered: 0,\n totalFailed: 0,\n deliveryRate: 0,\n periodStart: new Date().toISOString(),\n periodEnd: new Date().toISOString(),\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n },\n\n /**\n * Get template usage analytics\n */\n async getTemplateUsage(templateCode?: string) {\n try {\n const now = new Date();\n const monthAgo = new Date();\n monthAgo.setMonth(now.getMonth() - 1);\n\n if (templateCode) {\n // TODO: Implement getTemplateStats when available\n const stats = {\n sent: 0,\n delivered: 0,\n failed: 0,\n deliveryRate: 0,\n averageDeliveryTime: 0,\n };\n\n return {\n templateCode,\n totalUsage: stats.sent,\n successCount: stats.delivered,\n failureCount: stats.failed,\n successRate: stats.deliveryRate,\n lastUsed: new Date().toISOString(),\n averageDeliveryTime: stats.averageDeliveryTime,\n };\n }\n\n // Get usage for all templates by getting overall stats\n // TODO: provider.analytics.getUsage\n const usage = {\n breakdown: { byTemplate: {} },\n deliveryRate: 0,\n };\n\n const templateUsage = Object.entries(usage.breakdown.byTemplate).map(\n ([code, count]) => {\n const countNum = Number(count) || 0;\n const successCount = Math.round(\n countNum * (usage.deliveryRate / 100),\n );\n const failureCount = countNum - successCount;\n\n return {\n templateCode: code,\n totalUsage: countNum,\n successCount,\n failureCount,\n successRate: usage.deliveryRate,\n };\n },\n );\n\n return templateUsage.sort((a, b) => b.totalUsage - a.totalUsage);\n } catch (error) {\n console.warn(\"Failed to get template usage:\", error);\n return templateCode\n ? {\n templateCode,\n totalUsage: 0,\n successCount: 0,\n failureCount: 0,\n successRate: 0,\n error: error instanceof Error ? error.message : \"Unknown error\",\n }\n : [];\n }\n },\n\n /**\n * Generate usage reports\n */\n async generateReport(\n type: \"daily\" | \"weekly\" | \"monthly\",\n format: \"json\" | \"csv\" = \"json\",\n ) {\n try {\n const now = new Date();\n const periodStart = new Date();\n\n switch (type) {\n case \"daily\":\n periodStart.setDate(now.getDate() - 1);\n break;\n case \"weekly\":\n periodStart.setDate(now.getDate() - 7);\n break;\n case \"monthly\":\n periodStart.setMonth(now.getMonth() - 1);\n break;\n }\n\n // TODO: provider.analytics.getUsage\n const usage = {\n sentMessages: 0,\n deliveredMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveryRate: 0,\n failureRate: 0,\n breakdown: {\n byTemplate: {} as Record<string, number>,\n byDay: {} as Record<string, number>,\n byHour: {} as Record<string, number>,\n },\n };\n\n const templateUsage = await this.getTemplateUsage();\n const topTemplates = Array.isArray(templateUsage)\n ? templateUsage.slice(0, 3).map((t) => t.templateCode)\n : [];\n\n const data = {\n reportType: type,\n generatedAt: new Date().toISOString(),\n period: {\n from: periodStart.toISOString(),\n to: now.toISOString(),\n },\n summary: {\n totalMessages: usage.totalMessages,\n successRate: usage.deliveryRate,\n failureRate: usage.failureRate,\n topTemplates,\n },\n breakdown: {\n byTemplate: usage.breakdown.byTemplate,\n byDay: usage.breakdown.byDay,\n byHour: usage.breakdown.byHour,\n },\n };\n\n return format === \"csv\" ? this.toCsv(data) : data;\n } catch (error) {\n console.warn(\"Failed to generate report:\", error);\n const fallbackData = {\n reportType: type,\n generatedAt: new Date().toISOString(),\n error: error instanceof Error ? error.message : \"Unknown error\",\n summary: {\n totalMessages: 0,\n successRate: 0,\n failureRate: 0,\n topTemplates: [],\n },\n };\n return format === \"csv\" ? this.toCsv(fallbackData) : fallbackData;\n }\n },\n\n /**\n * Get delivery status breakdown\n */\n async getDeliveryStats(templateCode?: string) {\n try {\n const now = new Date();\n const weekAgo = new Date();\n weekAgo.setDate(now.getDate() - 7);\n\n // TODO: provider.analytics.getUsage\n const usage = {\n sentMessages: 0,\n deliveredMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveryRate: 0,\n failureRate: 0,\n breakdown: {\n byTemplate: {} as Record<string, number>,\n },\n };\n\n const filtered = usage;\n if (templateCode) {\n const templateCount = usage.breakdown.byTemplate[templateCode] || 0;\n const templateDelivered = Math.round(\n templateCount * (usage.deliveryRate / 100),\n );\n const templateFailed = Math.round(\n templateCount * (usage.failureRate / 100),\n );\n const templatePending =\n templateCount - templateDelivered - templateFailed;\n\n return {\n templateCode,\n delivered: templateDelivered,\n pending: templatePending,\n failed: templateFailed,\n total: templateCount,\n breakdown: {\n DELIVERED:\n templateCount > 0\n ? (templateDelivered / templateCount) * 100\n : 0,\n PENDING:\n templateCount > 0 ? (templatePending / templateCount) * 100 : 0,\n FAILED:\n templateCount > 0 ? (templateFailed / templateCount) * 100 : 0,\n },\n };\n }\n\n const pending = Math.max(\n 0,\n usage.totalMessages - usage.deliveredMessages - usage.failedMessages,\n );\n\n return {\n templateCode: undefined,\n delivered: usage.deliveredMessages,\n pending,\n failed: usage.failedMessages,\n total: usage.totalMessages,\n breakdown: {\n DELIVERED: usage.deliveryRate,\n PENDING:\n usage.totalMessages > 0\n ? (pending / usage.totalMessages) * 100\n : 0,\n FAILED: usage.failureRate,\n },\n };\n } catch (error) {\n console.warn(\"Failed to get delivery stats:\", error);\n return {\n templateCode,\n delivered: 0,\n pending: 0,\n failed: 0,\n total: 0,\n breakdown: {\n DELIVERED: 0,\n PENDING: 0,\n FAILED: 0,\n },\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n },\n\n /**\n * Convert data to CSV format\n */\n toCsv(data: any): string {\n // Simple CSV conversion\n return JSON.stringify(data, null, 2)\n .replace(/[{}]/g, \"\")\n .replace(/\"/g, \"\")\n .replace(/:/g, \",\");\n },\n };\n}\n"
|
|
5
|
+
"/**\n * K-Message: Korean Multi-Channel Messaging Platform\n * Unified package that re-exports core functionality for easy use\n */\n\nexport * from \"@k-msg/core\";\nexport { KMsg } from \"@k-msg/messaging\";\nexport { AligoProvider, IWINVProvider, MockProvider, SolapiProvider } from \"@k-msg/provider\";\nexport type { AligoConfig, IWINVConfig, SolapiConfig } from \"@k-msg/provider\";\n"
|
|
7
6
|
],
|
|
8
|
-
"mappings": "
|
|
9
|
-
"debugId": "
|
|
7
|
+
"mappings": "40BAKA,2CACqB,IAArB,8BACA",
|
|
8
|
+
"debugId": "7F66C101C1AC512E64756E2164756E21",
|
|
10
9
|
"names": []
|
|
11
10
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export*from"@k-msg/core";import{KMsg as i}from"@k-msg/messaging";import{AligoProvider as t,IWINVProvider as f,MockProvider as g,SolapiProvider as n}from"@k-msg/provider";export{n as SolapiProvider,g as MockProvider,i as KMsg,f as IWINVProvider,t as AligoProvider};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=9395ABDF7D7EDE6664756E2164756E21
|
|
4
4
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts"
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * K-Message: Korean Multi-Channel Messaging Platform\n * Unified package that re-exports core functionality for easy use\n */\n\
|
|
6
|
-
"import { IWINVProvider } from \"@k-msg/provider\";\n\n/**\n * Simple message sender for CLI/scripts\n *\n * @example\n * ```typescript\n * import { createKMsgSender } from 'k-msg/modules';\n *\n * const sender = createKMsgSender({\n * iwinvApiKey: process.env.IWINV_API_KEY!\n * });\n *\n * // User defines their own templates and variables\n * await sender.sendMessage('01012345678', 'USER_OTP_TEMPLATE', {\n * code: '123456',\n * serviceName: 'MyApp',\n * expireMinutes: 3\n * });\n * ```\n */\nexport function createKMsgSender(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Send message with custom template and variables\n * User defines their own template structure\n */\n async sendMessage(\n phoneNumber: string,\n templateCode: string,\n variables: Record<string, any>,\n ) {\n try {\n const result = (await provider.send({\n templateCode: templateCode as any,\n phoneNumber,\n variables,\n } as any)) as any;\n\n if (!result.isSuccess) {\n // Handle provider-level failure (e.g., invalid template, etc.)\n const error = result.error;\n const errorMessage =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : \"Provider reported a failure\";\n throw new Error(errorMessage);\n }\n\n const data = result.value;\n\n return {\n messageId: data.messageId,\n status: \"SENT\" as const,\n templateCode,\n phoneNumber,\n variables,\n error: null,\n sentAt: new Date().toISOString(),\n };\n } catch (error) {\n return {\n messageId: null,\n status: \"FAILED\" as const,\n templateCode,\n phoneNumber,\n variables,\n error: error instanceof Error ? error.message : \"Unknown error\",\n sentAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * Send bulk messages with user-defined template\n */\n async sendBulk(\n recipients: Array<{\n phoneNumber: string;\n variables: Record<string, any>;\n }>,\n templateCode: string,\n options?: {\n batchSize?: number;\n batchDelay?: number;\n },\n ) {\n const batchId = `batch_${Date.now()}`;\n const batchSize = options?.batchSize || 10;\n const batchDelay = options?.batchDelay || 1000;\n\n const results = [];\n let successCount = 0;\n let failureCount = 0;\n\n // Process recipients in batches\n for (let i = 0; i < recipients.length; i += batchSize) {\n const batch = recipients.slice(i, i + batchSize);\n\n // Process batch concurrently\n const batchPromises = batch.map(async (recipient) => {\n try {\n const result = (await provider.send({\n templateCode: templateCode as any,\n phoneNumber: recipient.phoneNumber,\n variables: recipient.variables,\n } as any)) as any;\n\n if (result.isSuccess && result.value.messageId) {\n successCount++;\n return {\n messageId: result.value.messageId,\n phoneNumber: recipient.phoneNumber,\n status: \"SENT\" as const,\n variables: recipient.variables,\n error: null,\n };\n } else {\n failureCount++;\n return {\n messageId: null,\n phoneNumber: recipient.phoneNumber,\n status: \"FAILED\" as const,\n variables: recipient.variables,\n error: result.error?.message || \"Unknown error\",\n };\n }\n } catch (error) {\n failureCount++;\n return {\n messageId: null,\n phoneNumber: recipient.phoneNumber,\n status: \"FAILED\" as const,\n variables: recipient.variables,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n });\n\n const batchResults = await Promise.all(batchPromises);\n results.push(...batchResults);\n\n // Add delay between batches (except for the last batch)\n if (i + batchSize < recipients.length && batchDelay > 0) {\n await new Promise((resolve) => setTimeout(resolve, batchDelay));\n }\n }\n\n return {\n batchId,\n templateCode,\n totalCount: recipients.length,\n successCount,\n failureCount,\n processedAt: new Date().toISOString(),\n results,\n };\n },\n\n /**\n * Check message delivery status\n */\n async getStatus(messageId: string) {\n try {\n const status = (await (provider as any).getStatus(messageId)) as any;\n\n return {\n messageId,\n status: status,\n checkedAt: new Date().toISOString(),\n deliveredAt:\n status === \"DELIVERED\" ? new Date().toISOString() : undefined,\n failedAt: status === \"FAILED\" ? new Date().toISOString() : undefined,\n };\n } catch (error) {\n return {\n messageId,\n status: \"UNKNOWN\",\n error:\n error instanceof Error ? error.message : \"Failed to check status\",\n checkedAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * Get platform instance for advanced usage (when implemented)\n */\n // getPlatform: () => platform\n };\n}\n\n/**\n * Template manager for CLI/scripts\n *\n * @example\n * ```typescript\n * const templates = createKMsgTemplates({ ... });\n * await templates.create('user_welcome', 'Welcome #{name}! Your account #{accountId} is ready.');\n * ```\n */\nexport function createKMsgTemplates(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Create template with user-defined structure\n */\n async create(templateCode: string, content: string, description: string) {\n try {\n // Parse variables from template content\n const variables = this.parseVariables(content);\n\n // TODO: Implement createTemplate when available\n const result = {\n templateId: templateCode,\n status: \"pending\",\n message: \"Template creation not implemented yet\",\n };\n\n return {\n id: result.templateId,\n code: result.templateId,\n content,\n description,\n variables,\n status: result.status,\n message: result.message,\n createdAt: new Date().toISOString(),\n };\n } catch (error) {\n return {\n id: null,\n code: templateCode,\n content,\n description,\n variables: this.parseVariables(content),\n status: \"FAILED\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n createdAt: new Date().toISOString(),\n };\n }\n },\n\n /**\n * List user templates\n */\n async list(filters?: { status?: string }) {\n try {\n // TODO: Implement templates.list when available\n return [];\n } catch (error) {\n console.warn(\"Failed to list templates:\", error);\n return [];\n }\n },\n\n /**\n * Validate template syntax and extract variables\n */\n async validate(content: string) {\n const variables = this.parseVariables(content);\n const errors: string[] = [];\n\n // Basic validation\n if (content.length === 0) {\n errors.push(\"Template content cannot be empty\");\n }\n\n if (content.length > 1000) {\n errors.push(\"Template content too long (max 1000 chars)\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n variables,\n };\n },\n\n /**\n * Parse variables from template content\n */\n parseVariables(content: string) {\n const matches = content.match(/#{([^}]+)}/g) || [];\n // Use a Set to efficiently get unique variable names\n const uniqueNames = new Set(matches.map((match) => match.slice(2, -1)));\n\n return Array.from(uniqueNames).map((name) => ({\n name,\n type: \"string\",\n required: true,\n }));\n },\n\n /**\n * Test template with sample variables\n */\n async test(templateCode: string, sampleVariables: Record<string, any>) {\n try {\n // TODO: Implement template validation when available\n const template = {\n code: templateCode,\n content: `Template ${templateCode}`,\n variables: [],\n };\n\n // Parse variables from template content\n const requiredVariables = this.parseVariables(template.content);\n const missingVariables = requiredVariables\n .filter((v) => v.required && !(v.name in sampleVariables))\n .map((v) => v.name);\n\n if (missingVariables.length > 0) {\n return {\n templateCode,\n renderedContent: null,\n isValid: false,\n errors: [\n `Missing required variables: ${missingVariables.join(\", \")}`,\n ],\n };\n }\n\n // Render template with sample variables\n let renderedContent = template.content;\n for (const [key, value] of Object.entries(sampleVariables)) {\n const regex = new RegExp(`#{${key}}`, \"g\");\n renderedContent = renderedContent.replace(regex, String(value));\n }\n\n // Check for unreplaced variables\n const unreplacedVars = renderedContent.match(/#{([^}]+)}/g);\n const warnings = unreplacedVars\n ? [`Unreplaced variables found: ${unreplacedVars.join(\", \")}`]\n : [];\n\n return {\n templateCode,\n renderedContent,\n isValid: !unreplacedVars,\n warnings,\n };\n } catch (error) {\n return {\n templateCode,\n renderedContent: null,\n isValid: false,\n error:\n error instanceof Error ? error.message : \"Template test failed\",\n };\n }\n },\n };\n}\n\n/**\n * Analytics reader for scripts/reporting\n */\nexport function createKMsgAnalytics(config: {\n iwinvApiKey: string;\n iwinvBaseUrl?: string;\n}) {\n const provider = new IWINVProvider({\n apiKey: config.iwinvApiKey,\n baseUrl: config.iwinvBaseUrl || \"https://alimtalk.bizservice.iwinv.kr\",\n debug: false,\n });\n\n return {\n /**\n * Get message statistics for specified period\n */\n async getMessageStats(period: \"day\" | \"week\" | \"month\" = \"day\") {\n try {\n const now = new Date();\n const periodStart = new Date();\n\n switch (period) {\n case \"day\":\n periodStart.setDate(now.getDate() - 1);\n break;\n case \"week\":\n periodStart.setDate(now.getDate() - 7);\n break;\n case \"month\":\n periodStart.setMonth(now.getMonth() - 1);\n break;\n }\n\n // TODO: Implement analytics when available\n const usage = {\n sentMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveredMessages: 0,\n deliveryRate: 0,\n breakdown: { byTemplate: {}, byDay: {}, byHour: {} },\n };\n\n return {\n period,\n totalSent: usage.sentMessages,\n totalDelivered: usage.deliveredMessages,\n totalFailed: usage.failedMessages,\n deliveryRate: usage.deliveryRate,\n periodStart: periodStart.toISOString(),\n periodEnd: now.toISOString(),\n breakdown: usage.breakdown,\n };\n } catch (error) {\n console.warn(\"Failed to get message stats:\", error);\n return {\n period,\n totalSent: 0,\n totalDelivered: 0,\n totalFailed: 0,\n deliveryRate: 0,\n periodStart: new Date().toISOString(),\n periodEnd: new Date().toISOString(),\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n },\n\n /**\n * Get template usage analytics\n */\n async getTemplateUsage(templateCode?: string) {\n try {\n const now = new Date();\n const monthAgo = new Date();\n monthAgo.setMonth(now.getMonth() - 1);\n\n if (templateCode) {\n // TODO: Implement getTemplateStats when available\n const stats = {\n sent: 0,\n delivered: 0,\n failed: 0,\n deliveryRate: 0,\n averageDeliveryTime: 0,\n };\n\n return {\n templateCode,\n totalUsage: stats.sent,\n successCount: stats.delivered,\n failureCount: stats.failed,\n successRate: stats.deliveryRate,\n lastUsed: new Date().toISOString(),\n averageDeliveryTime: stats.averageDeliveryTime,\n };\n }\n\n // Get usage for all templates by getting overall stats\n // TODO: provider.analytics.getUsage\n const usage = {\n breakdown: { byTemplate: {} },\n deliveryRate: 0,\n };\n\n const templateUsage = Object.entries(usage.breakdown.byTemplate).map(\n ([code, count]) => {\n const countNum = Number(count) || 0;\n const successCount = Math.round(\n countNum * (usage.deliveryRate / 100),\n );\n const failureCount = countNum - successCount;\n\n return {\n templateCode: code,\n totalUsage: countNum,\n successCount,\n failureCount,\n successRate: usage.deliveryRate,\n };\n },\n );\n\n return templateUsage.sort((a, b) => b.totalUsage - a.totalUsage);\n } catch (error) {\n console.warn(\"Failed to get template usage:\", error);\n return templateCode\n ? {\n templateCode,\n totalUsage: 0,\n successCount: 0,\n failureCount: 0,\n successRate: 0,\n error: error instanceof Error ? error.message : \"Unknown error\",\n }\n : [];\n }\n },\n\n /**\n * Generate usage reports\n */\n async generateReport(\n type: \"daily\" | \"weekly\" | \"monthly\",\n format: \"json\" | \"csv\" = \"json\",\n ) {\n try {\n const now = new Date();\n const periodStart = new Date();\n\n switch (type) {\n case \"daily\":\n periodStart.setDate(now.getDate() - 1);\n break;\n case \"weekly\":\n periodStart.setDate(now.getDate() - 7);\n break;\n case \"monthly\":\n periodStart.setMonth(now.getMonth() - 1);\n break;\n }\n\n // TODO: provider.analytics.getUsage\n const usage = {\n sentMessages: 0,\n deliveredMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveryRate: 0,\n failureRate: 0,\n breakdown: {\n byTemplate: {} as Record<string, number>,\n byDay: {} as Record<string, number>,\n byHour: {} as Record<string, number>,\n },\n };\n\n const templateUsage = await this.getTemplateUsage();\n const topTemplates = Array.isArray(templateUsage)\n ? templateUsage.slice(0, 3).map((t) => t.templateCode)\n : [];\n\n const data = {\n reportType: type,\n generatedAt: new Date().toISOString(),\n period: {\n from: periodStart.toISOString(),\n to: now.toISOString(),\n },\n summary: {\n totalMessages: usage.totalMessages,\n successRate: usage.deliveryRate,\n failureRate: usage.failureRate,\n topTemplates,\n },\n breakdown: {\n byTemplate: usage.breakdown.byTemplate,\n byDay: usage.breakdown.byDay,\n byHour: usage.breakdown.byHour,\n },\n };\n\n return format === \"csv\" ? this.toCsv(data) : data;\n } catch (error) {\n console.warn(\"Failed to generate report:\", error);\n const fallbackData = {\n reportType: type,\n generatedAt: new Date().toISOString(),\n error: error instanceof Error ? error.message : \"Unknown error\",\n summary: {\n totalMessages: 0,\n successRate: 0,\n failureRate: 0,\n topTemplates: [],\n },\n };\n return format === \"csv\" ? this.toCsv(fallbackData) : fallbackData;\n }\n },\n\n /**\n * Get delivery status breakdown\n */\n async getDeliveryStats(templateCode?: string) {\n try {\n const now = new Date();\n const weekAgo = new Date();\n weekAgo.setDate(now.getDate() - 7);\n\n // TODO: provider.analytics.getUsage\n const usage = {\n sentMessages: 0,\n deliveredMessages: 0,\n failedMessages: 0,\n totalMessages: 0,\n deliveryRate: 0,\n failureRate: 0,\n breakdown: {\n byTemplate: {} as Record<string, number>,\n },\n };\n\n const filtered = usage;\n if (templateCode) {\n const templateCount = usage.breakdown.byTemplate[templateCode] || 0;\n const templateDelivered = Math.round(\n templateCount * (usage.deliveryRate / 100),\n );\n const templateFailed = Math.round(\n templateCount * (usage.failureRate / 100),\n );\n const templatePending =\n templateCount - templateDelivered - templateFailed;\n\n return {\n templateCode,\n delivered: templateDelivered,\n pending: templatePending,\n failed: templateFailed,\n total: templateCount,\n breakdown: {\n DELIVERED:\n templateCount > 0\n ? (templateDelivered / templateCount) * 100\n : 0,\n PENDING:\n templateCount > 0 ? (templatePending / templateCount) * 100 : 0,\n FAILED:\n templateCount > 0 ? (templateFailed / templateCount) * 100 : 0,\n },\n };\n }\n\n const pending = Math.max(\n 0,\n usage.totalMessages - usage.deliveredMessages - usage.failedMessages,\n );\n\n return {\n templateCode: undefined,\n delivered: usage.deliveredMessages,\n pending,\n failed: usage.failedMessages,\n total: usage.totalMessages,\n breakdown: {\n DELIVERED: usage.deliveryRate,\n PENDING:\n usage.totalMessages > 0\n ? (pending / usage.totalMessages) * 100\n : 0,\n FAILED: usage.failureRate,\n },\n };\n } catch (error) {\n console.warn(\"Failed to get delivery stats:\", error);\n return {\n templateCode,\n delivered: 0,\n pending: 0,\n failed: 0,\n total: 0,\n breakdown: {\n DELIVERED: 0,\n PENDING: 0,\n FAILED: 0,\n },\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n },\n\n /**\n * Convert data to CSV format\n */\n toCsv(data: any): string {\n // Simple CSV conversion\n return JSON.stringify(data, null, 2)\n .replace(/[{}]/g, \"\")\n .replace(/\"/g, \"\")\n .replace(/:/g, \",\");\n },\n };\n}\n"
|
|
5
|
+
"/**\n * K-Message: Korean Multi-Channel Messaging Platform\n * Unified package that re-exports core functionality for easy use\n */\n\nexport * from \"@k-msg/core\";\nexport { KMsg } from \"@k-msg/messaging\";\nexport { AligoProvider, IWINVProvider, MockProvider, SolapiProvider } from \"@k-msg/provider\";\nexport type { AligoConfig, IWINVConfig, SolapiConfig } from \"@k-msg/provider\";\n"
|
|
7
6
|
],
|
|
8
|
-
"mappings": "
|
|
9
|
-
"debugId": "
|
|
7
|
+
"mappings": "AAKA,yBACA,eAAS,yBACT,wBAAS,mBAAe,kBAAe,oBAAc",
|
|
8
|
+
"debugId": "9395ABDF7D7EDE6664756E2164756E21",
|
|
10
9
|
"names": []
|
|
11
10
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "k-msg",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"packageManager": "bun@1.3.8",
|
|
5
5
|
"description": "K-Message: Korean Multi-Channel Messaging Platform - Unified Package",
|
|
6
6
|
"type": "module",
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
"build:types": "tsc",
|
|
22
22
|
"dev": "bun --watch src/index.ts",
|
|
23
23
|
"test": "bun test",
|
|
24
|
+
"test:unit": "bun test --testPathPattern='.*\\.test\\.(ts|js)$' --testTimeout=5000",
|
|
24
25
|
"clean": "rm -rf dist",
|
|
25
26
|
"pack": "bun pm pack",
|
|
26
27
|
"publish": "bun publish --access public"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@k-msg/core": "0.
|
|
30
|
-
"@k-msg/messaging": "0.
|
|
31
|
-
"@k-msg/template": "0.
|
|
32
|
-
"@k-msg/webhook": "0.
|
|
33
|
-
"@k-msg/analytics": "0.
|
|
34
|
-
"@k-msg/channel": "0.
|
|
35
|
-
"@k-msg/provider": "0.
|
|
30
|
+
"@k-msg/core": "0.5.0",
|
|
31
|
+
"@k-msg/messaging": "0.5.0",
|
|
32
|
+
"@k-msg/template": "0.5.0",
|
|
33
|
+
"@k-msg/webhook": "0.5.0",
|
|
34
|
+
"@k-msg/analytics": "0.5.0",
|
|
35
|
+
"@k-msg/channel": "0.5.0",
|
|
36
|
+
"@k-msg/provider": "0.5.0",
|
|
36
37
|
"zod": "^4.0.14"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
package/dist/modules/index.d.ts
DELETED
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple message sender for CLI/scripts
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* ```typescript
|
|
6
|
-
* import { createKMsgSender } from 'k-msg/modules';
|
|
7
|
-
*
|
|
8
|
-
* const sender = createKMsgSender({
|
|
9
|
-
* iwinvApiKey: process.env.IWINV_API_KEY!
|
|
10
|
-
* });
|
|
11
|
-
*
|
|
12
|
-
* // User defines their own templates and variables
|
|
13
|
-
* await sender.sendMessage('01012345678', 'USER_OTP_TEMPLATE', {
|
|
14
|
-
* code: '123456',
|
|
15
|
-
* serviceName: 'MyApp',
|
|
16
|
-
* expireMinutes: 3
|
|
17
|
-
* });
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export declare function createKMsgSender(config: {
|
|
21
|
-
iwinvApiKey: string;
|
|
22
|
-
iwinvBaseUrl?: string;
|
|
23
|
-
}): {
|
|
24
|
-
/**
|
|
25
|
-
* Send message with custom template and variables
|
|
26
|
-
* User defines their own template structure
|
|
27
|
-
*/
|
|
28
|
-
sendMessage(phoneNumber: string, templateCode: string, variables: Record<string, any>): Promise<{
|
|
29
|
-
messageId: any;
|
|
30
|
-
status: "SENT";
|
|
31
|
-
templateCode: string;
|
|
32
|
-
phoneNumber: string;
|
|
33
|
-
variables: Record<string, any>;
|
|
34
|
-
error: null;
|
|
35
|
-
sentAt: string;
|
|
36
|
-
} | {
|
|
37
|
-
messageId: null;
|
|
38
|
-
status: "FAILED";
|
|
39
|
-
templateCode: string;
|
|
40
|
-
phoneNumber: string;
|
|
41
|
-
variables: Record<string, any>;
|
|
42
|
-
error: string;
|
|
43
|
-
sentAt: string;
|
|
44
|
-
}>;
|
|
45
|
-
/**
|
|
46
|
-
* Send bulk messages with user-defined template
|
|
47
|
-
*/
|
|
48
|
-
sendBulk(recipients: Array<{
|
|
49
|
-
phoneNumber: string;
|
|
50
|
-
variables: Record<string, any>;
|
|
51
|
-
}>, templateCode: string, options?: {
|
|
52
|
-
batchSize?: number;
|
|
53
|
-
batchDelay?: number;
|
|
54
|
-
}): Promise<{
|
|
55
|
-
batchId: string;
|
|
56
|
-
templateCode: string;
|
|
57
|
-
totalCount: number;
|
|
58
|
-
successCount: number;
|
|
59
|
-
failureCount: number;
|
|
60
|
-
processedAt: string;
|
|
61
|
-
results: ({
|
|
62
|
-
messageId: any;
|
|
63
|
-
phoneNumber: string;
|
|
64
|
-
status: "SENT";
|
|
65
|
-
variables: Record<string, any>;
|
|
66
|
-
error: null;
|
|
67
|
-
} | {
|
|
68
|
-
messageId: null;
|
|
69
|
-
phoneNumber: string;
|
|
70
|
-
status: "FAILED";
|
|
71
|
-
variables: Record<string, any>;
|
|
72
|
-
error: any;
|
|
73
|
-
})[];
|
|
74
|
-
}>;
|
|
75
|
-
/**
|
|
76
|
-
* Check message delivery status
|
|
77
|
-
*/
|
|
78
|
-
getStatus(messageId: string): Promise<{
|
|
79
|
-
messageId: string;
|
|
80
|
-
status: any;
|
|
81
|
-
checkedAt: string;
|
|
82
|
-
deliveredAt: string | undefined;
|
|
83
|
-
failedAt: string | undefined;
|
|
84
|
-
error?: undefined;
|
|
85
|
-
} | {
|
|
86
|
-
messageId: string;
|
|
87
|
-
status: string;
|
|
88
|
-
error: string;
|
|
89
|
-
checkedAt: string;
|
|
90
|
-
deliveredAt?: undefined;
|
|
91
|
-
failedAt?: undefined;
|
|
92
|
-
}>;
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* Template manager for CLI/scripts
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* const templates = createKMsgTemplates({ ... });
|
|
100
|
-
* await templates.create('user_welcome', 'Welcome #{name}! Your account #{accountId} is ready.');
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export declare function createKMsgTemplates(config: {
|
|
104
|
-
iwinvApiKey: string;
|
|
105
|
-
iwinvBaseUrl?: string;
|
|
106
|
-
}): {
|
|
107
|
-
/**
|
|
108
|
-
* Create template with user-defined structure
|
|
109
|
-
*/
|
|
110
|
-
create(templateCode: string, content: string, description: string): Promise<{
|
|
111
|
-
id: string;
|
|
112
|
-
code: string;
|
|
113
|
-
content: string;
|
|
114
|
-
description: string;
|
|
115
|
-
variables: {
|
|
116
|
-
name: string;
|
|
117
|
-
type: string;
|
|
118
|
-
required: boolean;
|
|
119
|
-
}[];
|
|
120
|
-
status: string;
|
|
121
|
-
message: string;
|
|
122
|
-
createdAt: string;
|
|
123
|
-
error?: undefined;
|
|
124
|
-
} | {
|
|
125
|
-
id: null;
|
|
126
|
-
code: string;
|
|
127
|
-
content: string;
|
|
128
|
-
description: string;
|
|
129
|
-
variables: {
|
|
130
|
-
name: string;
|
|
131
|
-
type: string;
|
|
132
|
-
required: boolean;
|
|
133
|
-
}[];
|
|
134
|
-
status: string;
|
|
135
|
-
error: string;
|
|
136
|
-
createdAt: string;
|
|
137
|
-
message?: undefined;
|
|
138
|
-
}>;
|
|
139
|
-
/**
|
|
140
|
-
* List user templates
|
|
141
|
-
*/
|
|
142
|
-
list(filters?: {
|
|
143
|
-
status?: string;
|
|
144
|
-
}): Promise<never[]>;
|
|
145
|
-
/**
|
|
146
|
-
* Validate template syntax and extract variables
|
|
147
|
-
*/
|
|
148
|
-
validate(content: string): Promise<{
|
|
149
|
-
isValid: boolean;
|
|
150
|
-
errors: string[];
|
|
151
|
-
variables: {
|
|
152
|
-
name: string;
|
|
153
|
-
type: string;
|
|
154
|
-
required: boolean;
|
|
155
|
-
}[];
|
|
156
|
-
}>;
|
|
157
|
-
/**
|
|
158
|
-
* Parse variables from template content
|
|
159
|
-
*/
|
|
160
|
-
parseVariables(content: string): {
|
|
161
|
-
name: string;
|
|
162
|
-
type: string;
|
|
163
|
-
required: boolean;
|
|
164
|
-
}[];
|
|
165
|
-
/**
|
|
166
|
-
* Test template with sample variables
|
|
167
|
-
*/
|
|
168
|
-
test(templateCode: string, sampleVariables: Record<string, any>): Promise<{
|
|
169
|
-
templateCode: string;
|
|
170
|
-
renderedContent: null;
|
|
171
|
-
isValid: boolean;
|
|
172
|
-
errors: string[];
|
|
173
|
-
warnings?: undefined;
|
|
174
|
-
error?: undefined;
|
|
175
|
-
} | {
|
|
176
|
-
templateCode: string;
|
|
177
|
-
renderedContent: string;
|
|
178
|
-
isValid: boolean;
|
|
179
|
-
warnings: string[];
|
|
180
|
-
errors?: undefined;
|
|
181
|
-
error?: undefined;
|
|
182
|
-
} | {
|
|
183
|
-
templateCode: string;
|
|
184
|
-
renderedContent: null;
|
|
185
|
-
isValid: boolean;
|
|
186
|
-
error: string;
|
|
187
|
-
errors?: undefined;
|
|
188
|
-
warnings?: undefined;
|
|
189
|
-
}>;
|
|
190
|
-
};
|
|
191
|
-
/**
|
|
192
|
-
* Analytics reader for scripts/reporting
|
|
193
|
-
*/
|
|
194
|
-
export declare function createKMsgAnalytics(config: {
|
|
195
|
-
iwinvApiKey: string;
|
|
196
|
-
iwinvBaseUrl?: string;
|
|
197
|
-
}): {
|
|
198
|
-
/**
|
|
199
|
-
* Get message statistics for specified period
|
|
200
|
-
*/
|
|
201
|
-
getMessageStats(period?: "day" | "week" | "month"): Promise<{
|
|
202
|
-
period: "day" | "week" | "month";
|
|
203
|
-
totalSent: number;
|
|
204
|
-
totalDelivered: number;
|
|
205
|
-
totalFailed: number;
|
|
206
|
-
deliveryRate: number;
|
|
207
|
-
periodStart: string;
|
|
208
|
-
periodEnd: string;
|
|
209
|
-
breakdown: {
|
|
210
|
-
byTemplate: {};
|
|
211
|
-
byDay: {};
|
|
212
|
-
byHour: {};
|
|
213
|
-
};
|
|
214
|
-
error?: undefined;
|
|
215
|
-
} | {
|
|
216
|
-
period: "day" | "week" | "month";
|
|
217
|
-
totalSent: number;
|
|
218
|
-
totalDelivered: number;
|
|
219
|
-
totalFailed: number;
|
|
220
|
-
deliveryRate: number;
|
|
221
|
-
periodStart: string;
|
|
222
|
-
periodEnd: string;
|
|
223
|
-
error: string;
|
|
224
|
-
breakdown?: undefined;
|
|
225
|
-
}>;
|
|
226
|
-
/**
|
|
227
|
-
* Get template usage analytics
|
|
228
|
-
*/
|
|
229
|
-
getTemplateUsage(templateCode?: string): Promise<{
|
|
230
|
-
templateCode: string;
|
|
231
|
-
totalUsage: number;
|
|
232
|
-
successCount: number;
|
|
233
|
-
failureCount: number;
|
|
234
|
-
successRate: number;
|
|
235
|
-
}[] | {
|
|
236
|
-
templateCode: string;
|
|
237
|
-
totalUsage: number;
|
|
238
|
-
successCount: number;
|
|
239
|
-
failureCount: number;
|
|
240
|
-
successRate: number;
|
|
241
|
-
lastUsed: string;
|
|
242
|
-
averageDeliveryTime: number;
|
|
243
|
-
error?: undefined;
|
|
244
|
-
} | {
|
|
245
|
-
templateCode: string;
|
|
246
|
-
totalUsage: number;
|
|
247
|
-
successCount: number;
|
|
248
|
-
failureCount: number;
|
|
249
|
-
successRate: number;
|
|
250
|
-
error: string;
|
|
251
|
-
lastUsed?: undefined;
|
|
252
|
-
averageDeliveryTime?: undefined;
|
|
253
|
-
}>;
|
|
254
|
-
/**
|
|
255
|
-
* Generate usage reports
|
|
256
|
-
*/
|
|
257
|
-
generateReport(type: "daily" | "weekly" | "monthly", format?: "json" | "csv"): Promise<string | {
|
|
258
|
-
reportType: "daily" | "weekly" | "monthly";
|
|
259
|
-
generatedAt: string;
|
|
260
|
-
period: {
|
|
261
|
-
from: string;
|
|
262
|
-
to: string;
|
|
263
|
-
};
|
|
264
|
-
summary: {
|
|
265
|
-
totalMessages: number;
|
|
266
|
-
successRate: number;
|
|
267
|
-
failureRate: number;
|
|
268
|
-
topTemplates: string[];
|
|
269
|
-
};
|
|
270
|
-
breakdown: {
|
|
271
|
-
byTemplate: Record<string, number>;
|
|
272
|
-
byDay: Record<string, number>;
|
|
273
|
-
byHour: Record<string, number>;
|
|
274
|
-
};
|
|
275
|
-
} | {
|
|
276
|
-
reportType: "daily" | "weekly" | "monthly";
|
|
277
|
-
generatedAt: string;
|
|
278
|
-
error: string;
|
|
279
|
-
summary: {
|
|
280
|
-
totalMessages: number;
|
|
281
|
-
successRate: number;
|
|
282
|
-
failureRate: number;
|
|
283
|
-
topTemplates: never[];
|
|
284
|
-
};
|
|
285
|
-
}>;
|
|
286
|
-
/**
|
|
287
|
-
* Get delivery status breakdown
|
|
288
|
-
*/
|
|
289
|
-
getDeliveryStats(templateCode?: string): Promise<{
|
|
290
|
-
templateCode: string;
|
|
291
|
-
delivered: number;
|
|
292
|
-
pending: number;
|
|
293
|
-
failed: number;
|
|
294
|
-
total: number;
|
|
295
|
-
breakdown: {
|
|
296
|
-
DELIVERED: number;
|
|
297
|
-
PENDING: number;
|
|
298
|
-
FAILED: number;
|
|
299
|
-
};
|
|
300
|
-
error?: undefined;
|
|
301
|
-
} | {
|
|
302
|
-
templateCode: undefined;
|
|
303
|
-
delivered: number;
|
|
304
|
-
pending: number;
|
|
305
|
-
failed: number;
|
|
306
|
-
total: number;
|
|
307
|
-
breakdown: {
|
|
308
|
-
DELIVERED: number;
|
|
309
|
-
PENDING: number;
|
|
310
|
-
FAILED: number;
|
|
311
|
-
};
|
|
312
|
-
error?: undefined;
|
|
313
|
-
} | {
|
|
314
|
-
templateCode: string | undefined;
|
|
315
|
-
delivered: number;
|
|
316
|
-
pending: number;
|
|
317
|
-
failed: number;
|
|
318
|
-
total: number;
|
|
319
|
-
breakdown: {
|
|
320
|
-
DELIVERED: number;
|
|
321
|
-
PENDING: number;
|
|
322
|
-
FAILED: number;
|
|
323
|
-
};
|
|
324
|
-
error: string;
|
|
325
|
-
}>;
|
|
326
|
-
/**
|
|
327
|
-
* Convert data to CSV format
|
|
328
|
-
*/
|
|
329
|
-
toCsv(data: any): string;
|
|
330
|
-
};
|