@k-msg/core 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.
- package/README.md +244 -17
- package/dist/config.d.ts +206 -0
- package/dist/errors.d.ts +27 -0
- package/dist/health.d.ts +39 -0
- package/dist/index.d.ts +12 -565
- package/dist/index.js +23 -964
- package/dist/index.js.map +89 -1
- package/dist/index.mjs +27 -0
- package/dist/index.mjs.map +89 -0
- package/dist/logger.d.ts +62 -0
- package/dist/platform.d.ts +63 -0
- package/dist/provider-registry.d.ts +135 -0
- package/dist/provider.d.ts +36 -0
- package/dist/resilience/bulk-operation.d.ts +29 -0
- package/dist/resilience/circuit-breaker.d.ts +24 -0
- package/dist/resilience/error-recovery.d.ts +20 -0
- package/dist/resilience/graceful-degradation.d.ts +12 -0
- package/dist/resilience/health-monitor.d.ts +20 -0
- package/dist/resilience/index.d.ts +7 -0
- package/dist/resilience/rate-limiter.d.ts +12 -0
- package/dist/resilience/retry-handler.d.ts +20 -0
- package/dist/result.d.ts +61 -0
- package/dist/test-utils.d.ts +12 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/message.d.ts +34 -0
- package/dist/types/platform.d.ts +88 -0
- package/dist/types/provider.d.ts +76 -0
- package/dist/types/standard.d.ts +62 -0
- package/dist/universal-provider.d.ts +55 -0
- package/package.json +20 -9
- package/dist/index.cjs +0 -1015
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -565
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @k-msg/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The foundational package of the K-Message platform, providing essential types, error handling, retry mechanisms, and platform interfaces for Korean multi-channel messaging.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -12,12 +12,29 @@ bun add @k-msg/core
|
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
15
|
+
### 🏗️ **Core Platform Interface**
|
|
16
|
+
- **AlimTalkPlatform**: Unified messaging platform abstraction
|
|
17
|
+
- **Provider Management**: Multi-provider support and switching
|
|
18
|
+
- **Feature Flags**: Configurable platform capabilities
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
### ⚠️ **Comprehensive Error Handling**
|
|
21
|
+
- **KMessageError Hierarchy**: Structured error types for different scenarios
|
|
22
|
+
- **Error Context**: Rich error information with operation context
|
|
23
|
+
- **Error Recovery**: Built-in fallback and recovery strategies
|
|
24
|
+
|
|
25
|
+
### 🔄 **Retry & Resilience**
|
|
26
|
+
- **Exponential Backoff**: Smart retry with increasing delays
|
|
27
|
+
- **Circuit Breaker**: Automatic failure protection
|
|
28
|
+
- **Jitter**: Randomized delays to prevent thundering herd
|
|
29
|
+
|
|
30
|
+
### 💊 **Health Monitoring**
|
|
31
|
+
- **System Health Checks**: Multi-component health validation
|
|
32
|
+
- **Service Discovery**: Dynamic provider health monitoring
|
|
33
|
+
- **Dependency Tracking**: External service availability checks
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Basic Platform Setup
|
|
21
38
|
|
|
22
39
|
```typescript
|
|
23
40
|
import { AlimTalkPlatform } from '@k-msg/core';
|
|
@@ -32,29 +49,239 @@ const platform = new AlimTalkPlatform({
|
|
|
32
49
|
}
|
|
33
50
|
});
|
|
34
51
|
|
|
35
|
-
// Get platform
|
|
52
|
+
// Get platform capabilities
|
|
36
53
|
const info = platform.getInfo();
|
|
37
|
-
console.log(info);
|
|
54
|
+
console.log(`Platform: ${info.name}, Version: ${info.version}`);
|
|
55
|
+
console.log(`Supported providers: ${info.supportedProviders.join(', ')}`);
|
|
38
56
|
|
|
39
|
-
// Perform health check
|
|
57
|
+
// Perform comprehensive health check
|
|
40
58
|
const health = await platform.healthCheck();
|
|
41
|
-
console.log(health);
|
|
59
|
+
console.log(`Health: ${health.status}, Services: ${Object.keys(health.services).length}`);
|
|
42
60
|
```
|
|
43
61
|
|
|
44
|
-
|
|
62
|
+
### Error Handling Patterns
|
|
45
63
|
|
|
46
64
|
```typescript
|
|
47
|
-
import { KMessageError, Result } from '@k-msg/core';
|
|
65
|
+
import { KMessageError, KMessageErrorCode, Result } from '@k-msg/core';
|
|
66
|
+
|
|
67
|
+
// Method 1: Result Pattern (Recommended)
|
|
68
|
+
const result = await Result.fromPromise(
|
|
69
|
+
provider.sendMessage(message)
|
|
70
|
+
);
|
|
48
71
|
|
|
49
|
-
// Using Result pattern
|
|
50
|
-
const result = await Result.fromPromise(someAsyncOperation());
|
|
51
72
|
if (result.isSuccess) {
|
|
52
|
-
console.log(result.data);
|
|
73
|
+
console.log(`Message sent: ${result.data.messageId}`);
|
|
53
74
|
} else {
|
|
54
|
-
console.error(result.error);
|
|
75
|
+
console.error(`Send failed: ${result.error.message}`);
|
|
76
|
+
|
|
77
|
+
// Handle specific error types
|
|
78
|
+
if (result.error.code === KMessageErrorCode.PROVIDER_TIMEOUT) {
|
|
79
|
+
// Retry with different provider
|
|
80
|
+
} else if (result.error.code === KMessageErrorCode.TEMPLATE_NOT_FOUND) {
|
|
81
|
+
// Create template or use fallback
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Method 2: Try-Catch with Structured Errors
|
|
86
|
+
try {
|
|
87
|
+
const response = await provider.sendMessage(message);
|
|
88
|
+
console.log('Success:', response);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof KMessageError) {
|
|
91
|
+
console.error(`[${error.code}] ${error.message}`);
|
|
92
|
+
console.error('Context:', error.context);
|
|
93
|
+
|
|
94
|
+
// Access original cause if available
|
|
95
|
+
if (error.cause) {
|
|
96
|
+
console.error('Root cause:', error.cause);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// Handle unexpected errors
|
|
100
|
+
console.error('Unexpected error:', error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Retry Configuration
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { RetryManager, RetryConfig } from '@k-msg/core';
|
|
109
|
+
|
|
110
|
+
// Custom retry configuration
|
|
111
|
+
const retryConfig: RetryConfig = {
|
|
112
|
+
maxAttempts: 3,
|
|
113
|
+
baseDelay: 1000, // 1 second
|
|
114
|
+
maxDelay: 10000, // 10 seconds
|
|
115
|
+
backoffMultiplier: 2,
|
|
116
|
+
jitterType: 'full', // full, half, none
|
|
117
|
+
retryableErrors: [
|
|
118
|
+
KMessageErrorCode.NETWORK_ERROR,
|
|
119
|
+
KMessageErrorCode.PROVIDER_TIMEOUT,
|
|
120
|
+
KMessageErrorCode.RATE_LIMIT_EXCEEDED
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const retryManager = new RetryManager(retryConfig);
|
|
125
|
+
|
|
126
|
+
// Execute with retry
|
|
127
|
+
const result = await retryManager.execute(async () => {
|
|
128
|
+
return await provider.sendMessage(message);
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Health Check Implementation
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { HealthChecker, HealthStatus } from '@k-msg/core';
|
|
136
|
+
|
|
137
|
+
const healthChecker = new HealthChecker();
|
|
138
|
+
|
|
139
|
+
// Register custom health checks
|
|
140
|
+
healthChecker.register('database', async () => {
|
|
141
|
+
const connected = await checkDatabaseConnection();
|
|
142
|
+
return {
|
|
143
|
+
status: connected ? HealthStatus.HEALTHY : HealthStatus.UNHEALTHY,
|
|
144
|
+
details: { connected, lastCheck: new Date() }
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
healthChecker.register('external-api', async () => {
|
|
149
|
+
const responseTime = await measureApiResponseTime();
|
|
150
|
+
return {
|
|
151
|
+
status: responseTime < 1000 ? HealthStatus.HEALTHY : HealthStatus.DEGRADED,
|
|
152
|
+
details: { responseTime, threshold: 1000 }
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Perform comprehensive health check
|
|
157
|
+
const overallHealth = await healthChecker.checkAll();
|
|
158
|
+
console.log(`Overall status: ${overallHealth.status}`);
|
|
159
|
+
console.log(`Healthy services: ${overallHealth.healthyCount}/${overallHealth.totalCount}`);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## API Reference
|
|
163
|
+
|
|
164
|
+
### Core Types
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Platform configuration
|
|
168
|
+
interface AlimTalkPlatformConfig {
|
|
169
|
+
providers: string[];
|
|
170
|
+
defaultProvider: string;
|
|
171
|
+
features: PlatformFeatures;
|
|
172
|
+
retryConfig?: RetryConfig;
|
|
173
|
+
healthCheckConfig?: HealthCheckConfig;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Error types
|
|
177
|
+
enum KMessageErrorCode {
|
|
178
|
+
UNKNOWN = 'UNKNOWN',
|
|
179
|
+
NETWORK_ERROR = 'NETWORK_ERROR',
|
|
180
|
+
PROVIDER_ERROR = 'PROVIDER_ERROR',
|
|
181
|
+
TEMPLATE_ERROR = 'TEMPLATE_ERROR',
|
|
182
|
+
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
|
183
|
+
RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
|
|
184
|
+
// ... more error codes
|
|
55
185
|
}
|
|
186
|
+
|
|
187
|
+
// Health check results
|
|
188
|
+
interface HealthCheckResult {
|
|
189
|
+
status: HealthStatus;
|
|
190
|
+
services: Record<string, ServiceHealthInfo>;
|
|
191
|
+
timestamp: Date;
|
|
192
|
+
totalChecks: number;
|
|
193
|
+
passedChecks: number;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Test Utilities
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { TestData, TestAssertions } from '@k-msg/core/test-utils';
|
|
201
|
+
|
|
202
|
+
// Generate test data
|
|
203
|
+
const testMessage = TestData.createMessage({
|
|
204
|
+
provider: 'iwinv',
|
|
205
|
+
templateCode: 'AUTH_OTP',
|
|
206
|
+
phoneNumber: '01012345678'
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Test assertions
|
|
210
|
+
await TestAssertions.assertMessageSent(result);
|
|
211
|
+
TestAssertions.assertErrorType(error, KMessageErrorCode.TEMPLATE_NOT_FOUND);
|
|
56
212
|
```
|
|
57
213
|
|
|
214
|
+
## Advanced Usage
|
|
215
|
+
|
|
216
|
+
### Custom Error Types
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { KMessageError, KMessageErrorCode } from '@k-msg/core';
|
|
220
|
+
|
|
221
|
+
class CustomProviderError extends KMessageError {
|
|
222
|
+
constructor(
|
|
223
|
+
message: string,
|
|
224
|
+
public readonly providerId: string,
|
|
225
|
+
cause?: Error
|
|
226
|
+
) {
|
|
227
|
+
super(
|
|
228
|
+
message,
|
|
229
|
+
KMessageErrorCode.PROVIDER_ERROR,
|
|
230
|
+
{ operation: 'send_message', provider: providerId },
|
|
231
|
+
cause
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Plugin Integration
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { AlimTalkPlatform, PlatformPlugin } from '@k-msg/core';
|
|
241
|
+
|
|
242
|
+
class LoggingPlugin implements PlatformPlugin {
|
|
243
|
+
name = 'logging';
|
|
244
|
+
|
|
245
|
+
async initialize(platform: AlimTalkPlatform) {
|
|
246
|
+
platform.on('message_sent', (event) => {
|
|
247
|
+
console.log(`Message sent: ${event.messageId}`);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
platform.on('error', (event) => {
|
|
251
|
+
console.error(`Error: ${event.error.message}`);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const platform = new AlimTalkPlatform(config);
|
|
257
|
+
await platform.use(new LoggingPlugin());
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Best Practices
|
|
261
|
+
|
|
262
|
+
1. **Always use Result pattern** for error handling in production code
|
|
263
|
+
2. **Configure retries** appropriately for your use case
|
|
264
|
+
3. **Implement health checks** for all external dependencies
|
|
265
|
+
4. **Use structured logging** with error context information
|
|
266
|
+
5. **Monitor error rates** and adjust retry policies accordingly
|
|
267
|
+
|
|
268
|
+
## Testing
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Run unit tests
|
|
272
|
+
bun test
|
|
273
|
+
|
|
274
|
+
# Run with coverage
|
|
275
|
+
bun test --coverage
|
|
276
|
+
|
|
277
|
+
# Run specific test files
|
|
278
|
+
bun test retry.test.ts
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Contributing
|
|
282
|
+
|
|
283
|
+
See the main [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.
|
|
284
|
+
|
|
58
285
|
## License
|
|
59
286
|
|
|
60
|
-
MIT
|
|
287
|
+
MIT License - see [LICENSE](../../LICENSE) for details.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { LogLevel } from "./logger";
|
|
3
|
+
export declare const DatabaseConfigSchema: z.ZodObject<{
|
|
4
|
+
host: z.ZodDefault<z.ZodString>;
|
|
5
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
database: z.ZodString;
|
|
7
|
+
username: z.ZodString;
|
|
8
|
+
password: z.ZodString;
|
|
9
|
+
ssl: z.ZodDefault<z.ZodBoolean>;
|
|
10
|
+
maxConnections: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
connectionTimeout: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export declare const RedisConfigSchema: z.ZodObject<{
|
|
14
|
+
host: z.ZodDefault<z.ZodString>;
|
|
15
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
password: z.ZodOptional<z.ZodString>;
|
|
17
|
+
db: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
keyPrefix: z.ZodDefault<z.ZodString>;
|
|
19
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export declare const LoggerConfigSchema: z.ZodObject<{
|
|
22
|
+
level: z.ZodDefault<z.ZodEnum<typeof LogLevel>>;
|
|
23
|
+
enableConsole: z.ZodDefault<z.ZodBoolean>;
|
|
24
|
+
enableFile: z.ZodDefault<z.ZodBoolean>;
|
|
25
|
+
filePath: z.ZodOptional<z.ZodString>;
|
|
26
|
+
maxFileSize: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
maxFiles: z.ZodDefault<z.ZodNumber>;
|
|
28
|
+
enableJson: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
enableColors: z.ZodDefault<z.ZodBoolean>;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export declare const HealthConfigSchema: z.ZodObject<{
|
|
32
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
33
|
+
interval: z.ZodDefault<z.ZodNumber>;
|
|
34
|
+
retries: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
includeMetrics: z.ZodDefault<z.ZodBoolean>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export declare const IWINVConfigSchema: z.ZodObject<{
|
|
38
|
+
apiKey: z.ZodString;
|
|
39
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
40
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
retryAttempts: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
retryDelay: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
debug: z.ZodDefault<z.ZodBoolean>;
|
|
44
|
+
rateLimit: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
requests: z.ZodDefault<z.ZodNumber>;
|
|
46
|
+
perSecond: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export declare const SMSConfigSchema: z.ZodObject<{
|
|
50
|
+
provider: z.ZodEnum<{
|
|
51
|
+
iwinv: "iwinv";
|
|
52
|
+
aligo: "aligo";
|
|
53
|
+
coolsms: "coolsms";
|
|
54
|
+
}>;
|
|
55
|
+
apiKey: z.ZodString;
|
|
56
|
+
apiSecret: z.ZodOptional<z.ZodString>;
|
|
57
|
+
senderId: z.ZodString;
|
|
58
|
+
defaultCountryCode: z.ZodDefault<z.ZodString>;
|
|
59
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export declare const ServerConfigSchema: z.ZodObject<{
|
|
62
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
63
|
+
host: z.ZodDefault<z.ZodString>;
|
|
64
|
+
cors: z.ZodDefault<z.ZodObject<{
|
|
65
|
+
origins: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
66
|
+
credentials: z.ZodDefault<z.ZodBoolean>;
|
|
67
|
+
}, z.core.$strip>>;
|
|
68
|
+
maxRequestSize: z.ZodDefault<z.ZodNumber>;
|
|
69
|
+
requestTimeout: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
enableMetrics: z.ZodDefault<z.ZodBoolean>;
|
|
71
|
+
enableDocs: z.ZodDefault<z.ZodBoolean>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
export declare const QueueConfigSchema: z.ZodObject<{
|
|
74
|
+
maxConcurrency: z.ZodDefault<z.ZodNumber>;
|
|
75
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
76
|
+
retryDelay: z.ZodDefault<z.ZodNumber>;
|
|
77
|
+
maxAge: z.ZodDefault<z.ZodNumber>;
|
|
78
|
+
batchSize: z.ZodDefault<z.ZodNumber>;
|
|
79
|
+
processingInterval: z.ZodDefault<z.ZodNumber>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
export declare const KMessageConfigSchema: z.ZodObject<{
|
|
82
|
+
environment: z.ZodDefault<z.ZodEnum<{
|
|
83
|
+
development: "development";
|
|
84
|
+
staging: "staging";
|
|
85
|
+
production: "production";
|
|
86
|
+
}>>;
|
|
87
|
+
server: z.ZodDefault<z.ZodObject<{
|
|
88
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
89
|
+
host: z.ZodDefault<z.ZodString>;
|
|
90
|
+
cors: z.ZodDefault<z.ZodObject<{
|
|
91
|
+
origins: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
92
|
+
credentials: z.ZodDefault<z.ZodBoolean>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
maxRequestSize: z.ZodDefault<z.ZodNumber>;
|
|
95
|
+
requestTimeout: z.ZodDefault<z.ZodNumber>;
|
|
96
|
+
enableMetrics: z.ZodDefault<z.ZodBoolean>;
|
|
97
|
+
enableDocs: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
}, z.core.$strip>>;
|
|
99
|
+
database: z.ZodOptional<z.ZodObject<{
|
|
100
|
+
host: z.ZodDefault<z.ZodString>;
|
|
101
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
102
|
+
database: z.ZodString;
|
|
103
|
+
username: z.ZodString;
|
|
104
|
+
password: z.ZodString;
|
|
105
|
+
ssl: z.ZodDefault<z.ZodBoolean>;
|
|
106
|
+
maxConnections: z.ZodDefault<z.ZodNumber>;
|
|
107
|
+
connectionTimeout: z.ZodDefault<z.ZodNumber>;
|
|
108
|
+
}, z.core.$strip>>;
|
|
109
|
+
redis: z.ZodOptional<z.ZodObject<{
|
|
110
|
+
host: z.ZodDefault<z.ZodString>;
|
|
111
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
112
|
+
password: z.ZodOptional<z.ZodString>;
|
|
113
|
+
db: z.ZodDefault<z.ZodNumber>;
|
|
114
|
+
keyPrefix: z.ZodDefault<z.ZodString>;
|
|
115
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
116
|
+
}, z.core.$strip>>;
|
|
117
|
+
logger: z.ZodDefault<z.ZodObject<{
|
|
118
|
+
level: z.ZodDefault<z.ZodEnum<typeof LogLevel>>;
|
|
119
|
+
enableConsole: z.ZodDefault<z.ZodBoolean>;
|
|
120
|
+
enableFile: z.ZodDefault<z.ZodBoolean>;
|
|
121
|
+
filePath: z.ZodOptional<z.ZodString>;
|
|
122
|
+
maxFileSize: z.ZodDefault<z.ZodNumber>;
|
|
123
|
+
maxFiles: z.ZodDefault<z.ZodNumber>;
|
|
124
|
+
enableJson: z.ZodDefault<z.ZodBoolean>;
|
|
125
|
+
enableColors: z.ZodDefault<z.ZodBoolean>;
|
|
126
|
+
}, z.core.$strip>>;
|
|
127
|
+
health: z.ZodDefault<z.ZodObject<{
|
|
128
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
129
|
+
interval: z.ZodDefault<z.ZodNumber>;
|
|
130
|
+
retries: z.ZodDefault<z.ZodNumber>;
|
|
131
|
+
includeMetrics: z.ZodDefault<z.ZodBoolean>;
|
|
132
|
+
}, z.core.$strip>>;
|
|
133
|
+
queue: z.ZodDefault<z.ZodObject<{
|
|
134
|
+
maxConcurrency: z.ZodDefault<z.ZodNumber>;
|
|
135
|
+
maxRetries: z.ZodDefault<z.ZodNumber>;
|
|
136
|
+
retryDelay: z.ZodDefault<z.ZodNumber>;
|
|
137
|
+
maxAge: z.ZodDefault<z.ZodNumber>;
|
|
138
|
+
batchSize: z.ZodDefault<z.ZodNumber>;
|
|
139
|
+
processingInterval: z.ZodDefault<z.ZodNumber>;
|
|
140
|
+
}, z.core.$strip>>;
|
|
141
|
+
providers: z.ZodDefault<z.ZodObject<{
|
|
142
|
+
iwinv: z.ZodOptional<z.ZodObject<{
|
|
143
|
+
apiKey: z.ZodString;
|
|
144
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
145
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
146
|
+
retryAttempts: z.ZodDefault<z.ZodNumber>;
|
|
147
|
+
retryDelay: z.ZodDefault<z.ZodNumber>;
|
|
148
|
+
debug: z.ZodDefault<z.ZodBoolean>;
|
|
149
|
+
rateLimit: z.ZodDefault<z.ZodObject<{
|
|
150
|
+
requests: z.ZodDefault<z.ZodNumber>;
|
|
151
|
+
perSecond: z.ZodDefault<z.ZodNumber>;
|
|
152
|
+
}, z.core.$strip>>;
|
|
153
|
+
}, z.core.$strip>>;
|
|
154
|
+
sms: z.ZodOptional<z.ZodObject<{
|
|
155
|
+
provider: z.ZodEnum<{
|
|
156
|
+
iwinv: "iwinv";
|
|
157
|
+
aligo: "aligo";
|
|
158
|
+
coolsms: "coolsms";
|
|
159
|
+
}>;
|
|
160
|
+
apiKey: z.ZodString;
|
|
161
|
+
apiSecret: z.ZodOptional<z.ZodString>;
|
|
162
|
+
senderId: z.ZodString;
|
|
163
|
+
defaultCountryCode: z.ZodDefault<z.ZodString>;
|
|
164
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
165
|
+
}, z.core.$strip>>;
|
|
166
|
+
}, z.core.$strip>>;
|
|
167
|
+
features: z.ZodDefault<z.ZodObject<{
|
|
168
|
+
enableBulkSending: z.ZodDefault<z.ZodBoolean>;
|
|
169
|
+
enableScheduling: z.ZodDefault<z.ZodBoolean>;
|
|
170
|
+
enableAnalytics: z.ZodDefault<z.ZodBoolean>;
|
|
171
|
+
enableWebhooks: z.ZodDefault<z.ZodBoolean>;
|
|
172
|
+
enableTemplateCache: z.ZodDefault<z.ZodBoolean>;
|
|
173
|
+
maxTemplatesPerProvider: z.ZodDefault<z.ZodNumber>;
|
|
174
|
+
maxRecipientsPerBatch: z.ZodDefault<z.ZodNumber>;
|
|
175
|
+
}, z.core.$strip>>;
|
|
176
|
+
security: z.ZodDefault<z.ZodObject<{
|
|
177
|
+
apiKeyRequired: z.ZodDefault<z.ZodBoolean>;
|
|
178
|
+
rateLimitEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
179
|
+
maxRequestsPerMinute: z.ZodDefault<z.ZodNumber>;
|
|
180
|
+
enableCors: z.ZodDefault<z.ZodBoolean>;
|
|
181
|
+
trustedProxies: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
182
|
+
}, z.core.$strip>>;
|
|
183
|
+
}, z.core.$strip>;
|
|
184
|
+
export type DatabaseConfig = z.infer<typeof DatabaseConfigSchema>;
|
|
185
|
+
export type RedisConfig = z.infer<typeof RedisConfigSchema>;
|
|
186
|
+
export type ConfigLoggerConfig = z.infer<typeof LoggerConfigSchema>;
|
|
187
|
+
export type HealthConfig = z.infer<typeof HealthConfigSchema>;
|
|
188
|
+
export type IWINVConfig = z.infer<typeof IWINVConfigSchema>;
|
|
189
|
+
export type SMSConfig = z.infer<typeof SMSConfigSchema>;
|
|
190
|
+
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
191
|
+
export type QueueConfig = z.infer<typeof QueueConfigSchema>;
|
|
192
|
+
export type KMessageConfig = z.infer<typeof KMessageConfigSchema>;
|
|
193
|
+
export declare class ConfigLoader {
|
|
194
|
+
static loadFromEnv(): KMessageConfig;
|
|
195
|
+
static loadFromFile(filePath: string): Promise<KMessageConfig>;
|
|
196
|
+
static validate(config: any): KMessageConfig;
|
|
197
|
+
static getDefaults(): KMessageConfig;
|
|
198
|
+
}
|
|
199
|
+
type DeepPartial<T> = {
|
|
200
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
201
|
+
};
|
|
202
|
+
export declare const developmentConfig: DeepPartial<KMessageConfig>;
|
|
203
|
+
export declare const productionConfig: DeepPartial<KMessageConfig>;
|
|
204
|
+
export declare function mergeConfigs(base: KMessageConfig, override: Partial<KMessageConfig>): KMessageConfig;
|
|
205
|
+
export declare function validateProviderConfig(provider: "iwinv" | "sms", config: any): any;
|
|
206
|
+
export {};
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare enum KMsgErrorCode {
|
|
2
|
+
INVALID_REQUEST = "INVALID_REQUEST",
|
|
3
|
+
AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
|
|
4
|
+
INSUFFICIENT_BALANCE = "INSUFFICIENT_BALANCE",
|
|
5
|
+
TEMPLATE_NOT_FOUND = "TEMPLATE_NOT_FOUND",
|
|
6
|
+
RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED",
|
|
7
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
8
|
+
NETWORK_TIMEOUT = "NETWORK_TIMEOUT",
|
|
9
|
+
NETWORK_SERVICE_UNAVAILABLE = "NETWORK_SERVICE_UNAVAILABLE",
|
|
10
|
+
PROVIDER_ERROR = "PROVIDER_ERROR",
|
|
11
|
+
MESSAGE_SEND_FAILED = "MESSAGE_SEND_FAILED",
|
|
12
|
+
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
|
13
|
+
}
|
|
14
|
+
export declare class KMsgError extends Error {
|
|
15
|
+
readonly code: KMsgErrorCode;
|
|
16
|
+
readonly details?: Record<string, any>;
|
|
17
|
+
constructor(code: KMsgErrorCode, message: string, details?: Record<string, any>);
|
|
18
|
+
toJSON(): {
|
|
19
|
+
name: string;
|
|
20
|
+
code: KMsgErrorCode;
|
|
21
|
+
message: string;
|
|
22
|
+
details: Record<string, any> | undefined;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export declare const ErrorUtils: {
|
|
26
|
+
isRetryable: (error: any) => boolean;
|
|
27
|
+
};
|
package/dist/health.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface HealthStatus {
|
|
2
|
+
healthy: boolean;
|
|
3
|
+
timestamp: Date;
|
|
4
|
+
uptime: number;
|
|
5
|
+
version?: string;
|
|
6
|
+
services?: Record<string, ServiceHealth>;
|
|
7
|
+
metrics?: Record<string, any>;
|
|
8
|
+
}
|
|
9
|
+
export interface ServiceHealth {
|
|
10
|
+
healthy: boolean;
|
|
11
|
+
latency?: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
lastCheck?: Date;
|
|
14
|
+
}
|
|
15
|
+
export interface HealthCheckConfig {
|
|
16
|
+
timeout?: number;
|
|
17
|
+
interval?: number;
|
|
18
|
+
retries?: number;
|
|
19
|
+
includeMetrics?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare class HealthChecker {
|
|
22
|
+
private config;
|
|
23
|
+
private startTime;
|
|
24
|
+
private services;
|
|
25
|
+
private lastCheck;
|
|
26
|
+
constructor(config?: HealthCheckConfig);
|
|
27
|
+
registerService(name: string, checkFn: () => Promise<ServiceHealth>): void;
|
|
28
|
+
unregisterService(name: string): boolean;
|
|
29
|
+
clearServices(): void;
|
|
30
|
+
checkHealth(): Promise<HealthStatus>;
|
|
31
|
+
getLastKnownStatus(): HealthStatus;
|
|
32
|
+
private timeoutPromise;
|
|
33
|
+
private calculateAverageLatency;
|
|
34
|
+
}
|
|
35
|
+
export declare class SimpleHealthChecker {
|
|
36
|
+
static database(): () => Promise<ServiceHealth>;
|
|
37
|
+
static external(url: string, timeout?: number): () => Promise<ServiceHealth>;
|
|
38
|
+
static memory(maxUsageMB?: number): () => Promise<ServiceHealth>;
|
|
39
|
+
}
|