@mhbdev/sms 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +112 -24
  3. package/dist/contracts/pool.d.ts +97 -0
  4. package/dist/contracts/pool.d.ts.map +1 -0
  5. package/dist/contracts/pool.js +2 -0
  6. package/dist/contracts/pool.js.map +1 -0
  7. package/dist/errors/kavenegar-error.d.ts +1 -0
  8. package/dist/errors/kavenegar-error.d.ts.map +1 -1
  9. package/dist/errors/kavenegar-error.js.map +1 -1
  10. package/dist/errors/sms-error.d.ts +3 -0
  11. package/dist/errors/sms-error.d.ts.map +1 -1
  12. package/dist/errors/sms-error.js +2 -0
  13. package/dist/errors/sms-error.js.map +1 -1
  14. package/dist/errors/sms-ir-error.d.ts +1 -0
  15. package/dist/errors/sms-ir-error.d.ts.map +1 -1
  16. package/dist/errors/sms-ir-error.js.map +1 -1
  17. package/dist/index.d.ts +5 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/pool/health.d.ts +20 -0
  22. package/dist/pool/health.d.ts.map +1 -0
  23. package/dist/pool/health.js +58 -0
  24. package/dist/pool/health.js.map +1 -0
  25. package/dist/pool/sms-provider-pool.d.ts +46 -0
  26. package/dist/pool/sms-provider-pool.d.ts.map +1 -0
  27. package/dist/pool/sms-provider-pool.js +359 -0
  28. package/dist/pool/sms-provider-pool.js.map +1 -0
  29. package/dist/pool/strategies.d.ts +10 -0
  30. package/dist/pool/strategies.d.ts.map +1 -0
  31. package/dist/pool/strategies.js +39 -0
  32. package/dist/pool/strategies.js.map +1 -0
  33. package/dist/providers/kavenegar/kavenegar-api.d.ts.map +1 -1
  34. package/dist/providers/kavenegar/kavenegar-api.js +10 -0
  35. package/dist/providers/kavenegar/kavenegar-api.js.map +1 -1
  36. package/dist/providers/kavenegar/kavenegar-sms-provider.d.ts.map +1 -1
  37. package/dist/providers/kavenegar/kavenegar-sms-provider.js +9 -8
  38. package/dist/providers/kavenegar/kavenegar-sms-provider.js.map +1 -1
  39. package/dist/providers/sms-ir/sms-ir-api.d.ts.map +1 -1
  40. package/dist/providers/sms-ir/sms-ir-api.js +14 -0
  41. package/dist/providers/sms-ir/sms-ir-api.js.map +1 -1
  42. package/dist/providers/sms-ir/sms-ir-provider.d.ts.map +1 -1
  43. package/dist/providers/sms-ir/sms-ir-provider.js +6 -5
  44. package/dist/providers/sms-ir/sms-ir-provider.js.map +1 -1
  45. package/dist/transport/http.d.ts +2 -0
  46. package/dist/transport/http.d.ts.map +1 -1
  47. package/dist/transport/http.js +1 -1
  48. package/dist/transport/http.js.map +1 -1
  49. package/docs/capabilities.md +16 -11
  50. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.2.4
6
+
7
+ ### Patch Changes
8
+
9
+ - [#16](https://github.com/mhbdev/sms/pull/16) [`d248189`](https://github.com/mhbdev/sms/commit/d24818936f4b5be4362f7dce72d59e4c586e5625) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update the runtime Zod dependency to 4.6.7 to include upstream security fixes.
10
+
11
+ ## 0.2.3
12
+
13
+ ### Patch Changes
14
+
15
+ - [#12](https://github.com/mhbdev/sms/pull/12) [`1bca296`](https://github.com/mhbdev/sms/commit/1bca29622247b1f6297d57d921ecee0da83d22e8) Thanks [@mhbdev](https://github.com/mhbdev)! - Add `SmsProviderPool` with pluggable priority and weighted round-robin routing,
16
+ provider health tracking, safe send retry/failover, and typed adapters for
17
+ provider-specific batch operations. Send requests no longer use the legacy HTTP
18
+ retry policy; uncertain delivery outcomes stop with an explicit pool error.
19
+
5
20
  ## 0.2.2
6
21
 
7
22
  ### Patch Changes
package/README.md CHANGED
@@ -21,19 +21,19 @@ npm install @mhbdev/sms
21
21
  import { KavenegarSmsProvider } from "@mhbdev/sms/kavenegar";
22
22
 
23
23
  const sms = new KavenegarSmsProvider({
24
- apiKey: process.env.KAVENEGAR_API_KEY!,
25
- sender: "90005738",
24
+ apiKey: process.env.KAVENEGAR_API_KEY!,
25
+ sender: "90005738",
26
26
  });
27
27
 
28
28
  await sms.sendMessage({
29
- recipient: "+989121234567",
30
- message: "Your order is ready.",
29
+ recipient: "+989121234567",
30
+ message: "Your order is ready.",
31
31
  });
32
32
 
33
33
  await sms.sendTemplate({
34
- recipient: "+989121234567",
35
- template: "my-otp-pattern",
36
- parameters: ["123456"],
34
+ recipient: "+989121234567",
35
+ template: "my-otp-pattern",
36
+ parameters: ["123456"],
37
37
  });
38
38
  ```
39
39
 
@@ -42,9 +42,9 @@ options is the default sender number. A message-level `sender` overrides it:
42
42
 
43
43
  ```ts
44
44
  await sms.sendMessage({
45
- recipient: "+989121234567",
46
- message: "Sent from a specific line.",
47
- sender: "10004346",
45
+ recipient: "+989121234567",
46
+ message: "Sent from a specific line.",
47
+ sender: "10004346",
48
48
  });
49
49
  ```
50
50
 
@@ -58,19 +58,19 @@ returned by Kavenegar is preserved in the normalized result when provided.
58
58
  import { SmsIrProvider } from "@mhbdev/sms/sms-ir";
59
59
 
60
60
  const sms = new SmsIrProvider({
61
- apiKey: process.env.SMS_IR_API_KEY!,
62
- lineNumber: "300000000000",
61
+ apiKey: process.env.SMS_IR_API_KEY!,
62
+ lineNumber: "300000000000",
63
63
  });
64
64
 
65
65
  await sms.sendMessage({
66
- recipient: "09121234567",
67
- message: "Your order is ready.",
66
+ recipient: "09121234567",
67
+ message: "Your order is ready.",
68
68
  });
69
69
 
70
70
  await sms.sendTemplate({
71
- recipient: "09121234567",
72
- templateId: 123456,
73
- parameters: [{ name: "CODE", value: "123456" }],
71
+ recipient: "09121234567",
72
+ templateId: 123456,
73
+ parameters: [{ name: "CODE", value: "123456" }],
74
74
  });
75
75
  ```
76
76
 
@@ -106,13 +106,13 @@ because retrying after an unknown provider response can duplicate a paid SMS.
106
106
 
107
107
  ```ts
108
108
  const sms = new SmsIrProvider({
109
- apiKey: process.env.SMS_IR_API_KEY!,
110
- lineNumber: "300000000000",
111
- retry: {
112
- maxAttempts: 3,
113
- initialDelayMs: 250,
114
- maxDelayMs: 2_000,
115
- },
109
+ apiKey: process.env.SMS_IR_API_KEY!,
110
+ lineNumber: "300000000000",
111
+ retry: {
112
+ maxAttempts: 3,
113
+ initialDelayMs: 250,
114
+ maxDelayMs: 2_000,
115
+ },
116
116
  });
117
117
  ```
118
118
 
@@ -120,6 +120,94 @@ Provider failures are represented by `KavenegarError` or `SmsIrError`. Errors
120
120
  retain their original `cause`, stable error codes, provider status, HTTP status,
121
121
  and retry metadata without including API keys in messages.
122
122
 
123
+ Provider-level HTTP retries continue to apply to read operations. Send operations
124
+ are issued once per provider attempt; the pool only retries or fails over when a
125
+ provider explicitly reports that it rejected the send and marks that rejection
126
+ retryable. Timeouts, connection loss, and server errors with an uncertain result
127
+ produce an `SmsProviderPoolError` with `outcome: "unknown"` and stop routing.
128
+
129
+ ## Provider pools
130
+
131
+ `SmsProviderPool` combines provider adapters for raw, template, bulk, and native
132
+ batch sends. Adapters receive pool-neutral messages and can translate them to a
133
+ provider's own template or batch contract. A provider without an adapter for an
134
+ operation is skipped.
135
+
136
+ ```ts
137
+ import {
138
+ PriorityRoutingStrategy,
139
+ SmsProviderPool,
140
+ WeightedRoundRobinStrategy,
141
+ } from "@mhbdev/sms";
142
+ import { KavenegarSmsProvider } from "@mhbdev/sms/kavenegar";
143
+ import { SmsIrProvider } from "@mhbdev/sms/sms-ir";
144
+
145
+ const kavenegar = new KavenegarSmsProvider({
146
+ apiKey: process.env.KAVENEGAR_API_KEY!,
147
+ sender: "90005738",
148
+ });
149
+ const smsIr = new SmsIrProvider({
150
+ apiKey: process.env.SMS_IR_API_KEY!,
151
+ lineNumber: "300000000000",
152
+ });
153
+
154
+ const pool = new SmsProviderPool({
155
+ strategy: new PriorityRoutingStrategy(), // Or new WeightedRoundRobinStrategy()
156
+ providers: [
157
+ {
158
+ name: "kavenegar",
159
+ priority: 1,
160
+ sendMessage: (message) => kavenegar.sendMessage(message),
161
+ sendTemplate: (message) => kavenegar.sendTemplate(message),
162
+ sendBulk: (message) => kavenegar.sendBulk(message),
163
+ },
164
+ {
165
+ name: "sms.ir",
166
+ priority: 2,
167
+ weight: 2,
168
+ sendMessage: (message) =>
169
+ smsIr.sendMessage({
170
+ recipient: message.recipient,
171
+ message: message.message,
172
+ sendAt: message.sendAt,
173
+ signal: message.signal,
174
+ }),
175
+ // Map portable template fields to SMS.ir's templateId and named parameters here.
176
+ },
177
+ ],
178
+ circuitBreaker: { failureThreshold: 3, cooldownMs: 30_000 },
179
+ });
180
+
181
+ await pool.sendMessage({ recipient: "09121234567", message: "Your order is ready." });
182
+ ```
183
+
184
+ Priority routing tries providers in ascending `priority` order (default `0`).
185
+ Weighted round robin uses each provider's positive integer `weight` (default
186
+ `1`) and keeps state per strategy instance. Both strategies return remaining
187
+ eligible providers as failover candidates. Implement `SmsRoutingStrategy` to
188
+ provide a custom ordering, or `SmsProviderHealth` to use external health state.
189
+ For application adapters, set `deliveryOutcome: "rejected"` and
190
+ `retryable: true` on a `SmsProviderError` only when the provider confirms the
191
+ request was not accepted. Alternatively, use `classifyError` to map a provider's
192
+ documented error responses to that classification; all unclassified errors stop
193
+ with an unknown outcome.
194
+
195
+ The default in-memory circuit breaker opens after three health failures for 30
196
+ seconds, then permits one half-open probe. Set `circuitBreaker` to change those
197
+ defaults or pass a custom `health` implementation. Health state is local to the
198
+ pool instance. Optional `onEvent` reports selection, attempt, and circuit-state
199
+ changes; observer exceptions do not affect delivery.
200
+
201
+ Template adapters must map the template identifier and parameters explicitly.
202
+ Batch adapters are operation specific (`sendArray` versus `sendLikeToLike`) and
203
+ are never inferred.
204
+
205
+ The pool defaults to one attempt per provider. `maxAttemptsPerProvider` and the
206
+ backoff options enable retry after definitely rejected, retryable sends. They do
207
+ not enable retry after unknown outcomes. This is a deliberate safety change from
208
+ the legacy provider `retry` option: configured transport retries no longer replay
209
+ send requests, while reads retain their existing retry behavior.
210
+
123
211
  ## Development
124
212
 
125
213
  ```sh
@@ -0,0 +1,97 @@
1
+ import type { SmsBatchMessage, SmsBulkMessage, SmsBulkSendResult, SmsMessage, SmsSendResult, SmsTemplateMessage } from "./sms.js";
2
+ import type { SmsIrLikeToLikeMessage } from "./sms-ir.js";
3
+ export type SmsPoolOperation = "sendMessage" | "sendTemplate" | "sendBulk" | "sendArray" | "sendLikeToLike";
4
+ /** Adapters accept pool-neutral messages and translate to provider-specific inputs. */
5
+ export type SmsProviderPoolEntry = Readonly<{
6
+ name: string;
7
+ /** Smaller values are preferred by priority routing. */
8
+ priority?: number;
9
+ /** Positive integer used by weighted round robin. */
10
+ weight?: number;
11
+ sendMessage?: (message: SmsMessage) => Promise<SmsSendResult>;
12
+ sendTemplate?: (message: SmsTemplateMessage) => Promise<SmsSendResult>;
13
+ sendBulk?: (message: SmsBulkMessage) => Promise<SmsBulkSendResult>;
14
+ /** Typed adapter for a provider's per-recipient batch operation. */
15
+ sendArray?: (messages: readonly SmsBatchMessage[], options?: Readonly<{
16
+ signal?: AbortSignal;
17
+ }>) => Promise<readonly SmsSendResult[]>;
18
+ /** Typed adapter for a provider's per-recipient-message batch operation. */
19
+ sendLikeToLike?: (message: SmsIrLikeToLikeMessage) => Promise<SmsBulkSendResult>;
20
+ }>;
21
+ export type SmsPoolFailureClassification = Readonly<{
22
+ outcome: "rejected" | "unknown";
23
+ retryable: boolean;
24
+ retryAfterMs?: number;
25
+ code?: string;
26
+ httpStatus?: number;
27
+ providerStatus?: number | string;
28
+ }>;
29
+ export type SmsPoolAttempt = Readonly<{
30
+ provider: string;
31
+ operation: SmsPoolOperation;
32
+ outcome: "accepted" | "rejected" | "unknown";
33
+ code?: string;
34
+ httpStatus?: number;
35
+ providerStatus?: number | string;
36
+ retryable?: boolean;
37
+ }>;
38
+ export type SmsPoolEvent = Readonly<{
39
+ type: "provider-selected";
40
+ provider: string;
41
+ operation: SmsPoolOperation;
42
+ attempt: number;
43
+ }> | Readonly<{
44
+ type: "attempt-succeeded";
45
+ provider: string;
46
+ operation: SmsPoolOperation;
47
+ attempt: number;
48
+ }> | Readonly<{
49
+ type: "attempt-failed";
50
+ provider: string;
51
+ operation: SmsPoolOperation;
52
+ attempt: number;
53
+ outcome: "rejected" | "unknown";
54
+ retryable: boolean;
55
+ }> | Readonly<{
56
+ type: "circuit-state-changed";
57
+ provider: string;
58
+ state: SmsProviderCircuitState;
59
+ }>;
60
+ export type SmsProviderCircuitState = "closed" | "open" | "half-open";
61
+ export type SmsRoutingContext = Readonly<{
62
+ operation: SmsPoolOperation;
63
+ providers: readonly SmsProviderPoolEntry[];
64
+ }>;
65
+ export interface SmsRoutingStrategy {
66
+ order(context: SmsRoutingContext): readonly string[];
67
+ }
68
+ export interface SmsProviderHealth {
69
+ getState(provider: string): SmsProviderCircuitState;
70
+ /** Acquires a normal slot or the single half-open probe slot. */
71
+ acquire(provider: string): boolean;
72
+ /** Releases an acquired half-open probe when no provider request was made. */
73
+ release(provider: string): void;
74
+ recordSuccess(provider: string): void;
75
+ recordFailure(provider: string): void;
76
+ }
77
+ export type SmsProviderPoolOptions = Readonly<{
78
+ providers: readonly SmsProviderPoolEntry[];
79
+ strategy?: SmsRoutingStrategy;
80
+ health?: SmsProviderHealth;
81
+ circuitBreaker?: Readonly<{
82
+ failureThreshold?: number;
83
+ cooldownMs?: number;
84
+ now?: () => number;
85
+ }>;
86
+ maxAttemptsPerProvider?: number;
87
+ initialDelayMs?: number;
88
+ maxDelayMs?: number;
89
+ backoffMultiplier?: number;
90
+ sleep?: (delayMs: number, signal?: AbortSignal) => Promise<void>;
91
+ onEvent?: (event: SmsPoolEvent) => void;
92
+ classifyError?: (error: unknown, provider: SmsProviderPoolEntry, operation: SmsPoolOperation) => SmsPoolFailureClassification;
93
+ }>;
94
+ export type SmsPoolBatchInput = readonly SmsBatchMessage[];
95
+ export type SmsPoolBatchResult = readonly SmsSendResult[];
96
+ export type SmsPoolLikeToLikeInput = SmsIrLikeToLikeMessage;
97
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/contracts/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/contracts/pool.ts"],"names":[],"mappings":""}
@@ -6,6 +6,7 @@ export declare class KavenegarError extends SmsProviderError {
6
6
  providerStatus?: number | string;
7
7
  retryable?: boolean;
8
8
  retryAfterMs?: number;
9
+ deliveryOutcome?: "rejected" | "unknown";
9
10
  }>);
10
11
  }
11
12
  //# sourceMappingURL=kavenegar-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kavenegar-error.d.ts","sourceRoot":"","sources":["../../src/errors/kavenegar-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,cAAe,SAAQ,gBAAgB;IACnD,YACC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,QAAQ,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACtB,CAAM,EAOP;CACD"}
1
+ {"version":3,"file":"kavenegar-error.d.ts","sourceRoot":"","sources":["../../src/errors/kavenegar-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,cAAe,SAAQ,gBAAgB;IACnD,YACC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,QAAQ,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;KACzC,CAAM,EAOP;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"kavenegar-error.js","sourceRoot":"","sources":["../../src/errors/kavenegar-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACnD,YACC,OAAe,EACf,OAAO,GAMF,EAAE;QAEP,KAAK,CAAC,OAAO,EAAE;YACd,GAAG,OAAO;YACV,IAAI,EAAE,iBAAiB;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC9B,CAAC;CACD"}
1
+ {"version":3,"file":"kavenegar-error.js","sourceRoot":"","sources":["../../src/errors/kavenegar-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACnD,YACC,OAAe,EACf,OAAO,GAOF,EAAE;QAEP,KAAK,CAAC,OAAO,EAAE;YACd,GAAG,OAAO;YACV,IAAI,EAAE,iBAAiB;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC9B,CAAC;CACD"}
@@ -5,6 +5,8 @@ export type SmsErrorOptions = Readonly<{
5
5
  providerStatus?: number | string;
6
6
  retryable?: boolean;
7
7
  retryAfterMs?: number;
8
+ /** Whether a send was definitely rejected or may have been accepted. */
9
+ deliveryOutcome?: "rejected" | "unknown";
8
10
  }>;
9
11
  export declare class SmsProviderError extends Error {
10
12
  readonly code: string;
@@ -13,6 +15,7 @@ export declare class SmsProviderError extends Error {
13
15
  readonly providerStatus?: number | string;
14
16
  readonly retryable?: boolean;
15
17
  readonly retryAfterMs?: number;
18
+ readonly deliveryOutcome?: "rejected" | "unknown";
16
19
  constructor(message: string, options?: SmsErrorOptions);
17
20
  }
18
21
  export declare class SmsValidationError extends SmsProviderError {
@@ -1 +1 @@
1
- {"version":3,"file":"sms-error.d.ts","sourceRoot":"","sources":["../../src/errors/sms-error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,QAAQ;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,EAQzD;CACD;AAED,qBAAa,kBAAmB,SAAQ,gBAAgB;IACvD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAM,EAGvE;CACD;AAED,qBAAa,iBAAkB,SAAQ,gBAAgB;IACtD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAM,EAGvE;CACD"}
1
+ {"version":3,"file":"sms-error.d.ts","sourceRoot":"","sources":["../../src/errors/sms-error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACzC,CAAC,CAAC;AAEH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,QAAQ;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAElD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,EASzD;CACD;AAED,qBAAa,kBAAmB,SAAQ,gBAAgB;IACvD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAM,EAGvE;CACD;AAED,qBAAa,iBAAkB,SAAQ,gBAAgB;IACtD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAM,EAGvE;CACD"}
@@ -5,6 +5,7 @@ export class SmsProviderError extends Error {
5
5
  providerStatus;
6
6
  retryable;
7
7
  retryAfterMs;
8
+ deliveryOutcome;
8
9
  constructor(message, options = {}) {
9
10
  super(message, { cause: options.cause });
10
11
  this.name = "SmsProviderError";
@@ -13,6 +14,7 @@ export class SmsProviderError extends Error {
13
14
  this.providerStatus = options.providerStatus;
14
15
  this.retryable = options.retryable;
15
16
  this.retryAfterMs = options.retryAfterMs;
17
+ this.deliveryOutcome = options.deliveryOutcome;
16
18
  }
17
19
  }
18
20
  export class SmsValidationError extends SmsProviderError {
@@ -1 +1 @@
1
- {"version":3,"file":"sms-error.js","sourceRoot":"","sources":["../../src/errors/sms-error.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACjC,IAAI,CAAS;IACb,aAAa,GAAG,IAAI,CAAC;IACrB,UAAU,CAAU;IACpB,cAAc,CAAmB;IACjC,SAAS,CAAW;IACpB,YAAY,CAAU;IAE/B,YAAY,OAAe,EAAE,OAAO,GAAoB,EAAE;QACzD,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,oBAAoB,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC1C,CAAC;CACD;AAED,MAAM,OAAO,kBAAmB,SAAQ,gBAAgB;IACvD,YAAY,OAAe,EAAE,OAAO,GAAkC,EAAE;QACvE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IAClC,CAAC;CACD;AAED,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IACtD,YAAY,OAAe,EAAE,OAAO,GAAkC,EAAE;QACvE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IACjC,CAAC;CACD"}
1
+ {"version":3,"file":"sms-error.js","sourceRoot":"","sources":["../../src/errors/sms-error.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACjC,IAAI,CAAS;IACb,aAAa,GAAG,IAAI,CAAC;IACrB,UAAU,CAAU;IACpB,cAAc,CAAmB;IACjC,SAAS,CAAW;IACpB,YAAY,CAAU;IACtB,eAAe,CAA0B;IAElD,YAAY,OAAe,EAAE,OAAO,GAAoB,EAAE;QACzD,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,oBAAoB,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAChD,CAAC;CACD;AAED,MAAM,OAAO,kBAAmB,SAAQ,gBAAgB;IACvD,YAAY,OAAe,EAAE,OAAO,GAAkC,EAAE;QACvE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IAClC,CAAC;CACD;AAED,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IACtD,YAAY,OAAe,EAAE,OAAO,GAAkC,EAAE;QACvE,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IACjC,CAAC;CACD"}
@@ -6,6 +6,7 @@ export declare class SmsIrError extends SmsProviderError {
6
6
  providerStatus?: number | string;
7
7
  retryable?: boolean;
8
8
  retryAfterMs?: number;
9
+ deliveryOutcome?: "rejected" | "unknown";
9
10
  }>);
10
11
  }
11
12
  //# sourceMappingURL=sms-ir-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sms-ir-error.d.ts","sourceRoot":"","sources":["../../src/errors/sms-ir-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,UAAW,SAAQ,gBAAgB;IAC/C,YACC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,QAAQ,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACtB,CAAM,EAOP;CACD"}
1
+ {"version":3,"file":"sms-ir-error.d.ts","sourceRoot":"","sources":["../../src/errors/sms-ir-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,qBAAa,UAAW,SAAQ,gBAAgB;IAC/C,YACC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,QAAQ,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;KACzC,CAAM,EAOP;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"sms-ir-error.js","sourceRoot":"","sources":["../../src/errors/sms-ir-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,OAAO,UAAW,SAAQ,gBAAgB;IAC/C,YACC,OAAe,EACf,OAAO,GAMF,EAAE;QAEP,KAAK,CAAC,OAAO,EAAE;YACd,GAAG,OAAO;YACV,IAAI,EAAE,cAAc;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC1B,CAAC;CACD"}
1
+ {"version":3,"file":"sms-ir-error.js","sourceRoot":"","sources":["../../src/errors/sms-ir-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,OAAO,UAAW,SAAQ,gBAAgB;IAC/C,YACC,OAAe,EACf,OAAO,GAOF,EAAE;QAEP,KAAK,CAAC,OAAO,EAAE;YACd,GAAG,OAAO;YACV,IAAI,EAAE,cAAc;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC1B,CAAC;CACD"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  export type { SmsHttpFetcher, SmsHttpOptions } from "./contracts/http.js";
2
2
  export type { KavenegarBulkRequest, KavenegarBulkResult, KavenegarCancellationResult, KavenegarCountQuery, KavenegarCountResult, KavenegarOutboxCountQuery, KavenegarReceivedMessage, KavenegarReceiveQuery, KavenegarSendArrayMessage, KavenegarSendResult, KavenegarSmsProviderOptions, KavenegarStatusQuery, KavenegarStatusResult, KavenegarTemplateMessage, } from "./contracts/kavenegar.js";
3
+ export type { SmsPoolAttempt, SmsPoolBatchInput, SmsPoolBatchResult, SmsPoolEvent, SmsPoolFailureClassification, SmsPoolLikeToLikeInput, SmsPoolOperation, SmsProviderCircuitState, SmsProviderHealth, SmsProviderPoolEntry, SmsProviderPoolOptions, SmsRoutingContext, SmsRoutingStrategy, } from "./contracts/pool.js";
3
4
  export type { SmsBatchMessage, SmsBulkMessage, SmsBulkSender, SmsBulkSendResult, SmsCancellationResult, SmsCollection, SmsDeliveryStatus, SmsDeliveryStatusQuery, SmsDeliveryStatusReader, SmsInboxReader, SmsMessage, SmsMessageCancellationRequest, SmsMessageScheduler, SmsMessageSender, SmsPackScheduler, SmsPage, SmsReceivedMessage, SmsScheduler, SmsSendResult, SmsSendStatus, SmsTemplateMessage, SmsTemplateSender, } from "./contracts/sms.js";
4
5
  export type { SmsIrBulkMessage, SmsIrBulkSendResult, SmsIrCancellationResult, SmsIrLikeToLikeMessage, SmsIrMessage, SmsIrMessageStatus, SmsIrPackMessage, SmsIrPackQuery, SmsIrPackSummary, SmsIrParameter, SmsIrProviderOptions, SmsIrSendResult, SmsIrStatusQuery, SmsIrTemplateMessage, } from "./contracts/sms-ir.js";
5
6
  export { KavenegarError } from "./errors/kavenegar-error.js";
6
7
  export { SmsProviderError, SmsTransportError, SmsValidationError, } from "./errors/sms-error.js";
7
8
  export { SmsIrError } from "./errors/sms-ir-error.js";
9
+ export type { InMemoryCircuitBreakerOptions } from "./pool/health.js";
10
+ export { InMemoryCircuitBreaker } from "./pool/health.js";
11
+ export { SmsProviderPool, SmsProviderPoolError } from "./pool/sms-provider-pool.js";
12
+ export { PriorityRoutingStrategy, WeightedRoundRobinStrategy, } from "./pool/strategies.js";
8
13
  export { parseKavenegarCancellationResponse, parseKavenegarCountResponse, parseKavenegarPayload, parseKavenegarReceivedResponse, parseKavenegarResponse, parseKavenegarSendArrayResponse, parseKavenegarSendEntries, parseKavenegarStatusResponse, } from "./providers/kavenegar/kavenegar-api.js";
9
14
  export { KavenegarSmsProvider } from "./providers/kavenegar/kavenegar-sms-provider.js";
10
15
  export { parseSmsIrBulkResult, parseSmsIrCancellationResult, parseSmsIrMessageStatus, parseSmsIrPackMessages, parseSmsIrPackSummaries, parseSmsIrPayload, parseSmsIrSendResult, } from "./providers/sms-ir/sms-ir-api.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1E,YAAY,EACX,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,2BAA2B,EAC3B,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,UAAU,EACV,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACX,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACN,kCAAkC,EAClC,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,EACN,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,aAAa,EACb,aAAa,IAAI,gBAAgB,GACjC,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1E,YAAY,EACX,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,2BAA2B,EAC3B,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,4BAA4B,EAC5B,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACX,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,UAAU,EACV,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACX,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,YAAY,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EACN,uBAAuB,EACvB,0BAA0B,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,kCAAkC,EAClC,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,EACN,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,aAAa,EACb,aAAa,IAAI,gBAAgB,GACjC,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  export { KavenegarError } from "./errors/kavenegar-error.js";
2
2
  export { SmsProviderError, SmsTransportError, SmsValidationError, } from "./errors/sms-error.js";
3
3
  export { SmsIrError } from "./errors/sms-ir-error.js";
4
+ export { InMemoryCircuitBreaker } from "./pool/health.js";
5
+ export { SmsProviderPool, SmsProviderPoolError } from "./pool/sms-provider-pool.js";
6
+ export { PriorityRoutingStrategy, WeightedRoundRobinStrategy, } from "./pool/strategies.js";
4
7
  export { parseKavenegarCancellationResponse, parseKavenegarCountResponse, parseKavenegarPayload, parseKavenegarReceivedResponse, parseKavenegarResponse, parseKavenegarSendArrayResponse, parseKavenegarSendEntries, parseKavenegarStatusResponse, } from "./providers/kavenegar/kavenegar-api.js";
5
8
  export { KavenegarSmsProvider } from "./providers/kavenegar/kavenegar-sms-provider.js";
6
9
  export { parseSmsIrBulkResult, parseSmsIrCancellationResult, parseSmsIrMessageStatus, parseSmsIrPackMessages, parseSmsIrPackSummaries, parseSmsIrPayload, parseSmsIrSendResult, } from "./providers/sms-ir/sms-ir-api.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyDA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACN,kCAAkC,EAClC,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,EACN,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,aAAa,EACb,aAAa,IAAI,gBAAgB,GACjC,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwEA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EACN,uBAAuB,EACvB,0BAA0B,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,kCAAkC,EAClC,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,EACN,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACN,aAAa,EACb,aAAa,IAAI,gBAAgB,GACjC,MAAM,uCAAuC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { SmsProviderCircuitState, SmsProviderHealth } from "../contracts/pool.js";
2
+ export type InMemoryCircuitBreakerOptions = Readonly<{
3
+ failureThreshold?: number;
4
+ cooldownMs?: number;
5
+ now?: () => number;
6
+ }>;
7
+ export declare class InMemoryCircuitBreaker implements SmsProviderHealth {
8
+ private readonly circuits;
9
+ private readonly failureThreshold;
10
+ private readonly cooldownMs;
11
+ private readonly now;
12
+ constructor(options?: InMemoryCircuitBreakerOptions);
13
+ getState(provider: string): SmsProviderCircuitState;
14
+ acquire(provider: string): boolean;
15
+ release(provider: string): void;
16
+ recordSuccess(provider: string): void;
17
+ recordFailure(provider: string): void;
18
+ private get;
19
+ }
20
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/pool/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEvF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB,CAAC,CAAC;AAIH,qBAAa,sBAAuB,YAAW,iBAAiB;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IAEnC,YAAY,OAAO,GAAE,6BAAkC,EAQtD;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CAKlD;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMjC;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE9B;IAED,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKpC;IAED,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAOpC;IAED,OAAO,CAAC,GAAG;CAQX"}
@@ -0,0 +1,58 @@
1
+ export class InMemoryCircuitBreaker {
2
+ circuits = new Map();
3
+ failureThreshold;
4
+ cooldownMs;
5
+ now;
6
+ constructor(options = {}) {
7
+ this.failureThreshold = options.failureThreshold ?? 3;
8
+ this.cooldownMs = options.cooldownMs ?? 30_000;
9
+ this.now = options.now ?? Date.now;
10
+ if (!Number.isSafeInteger(this.failureThreshold) || this.failureThreshold < 1)
11
+ throw new TypeError("Circuit failureThreshold must be a positive integer");
12
+ if (!Number.isFinite(this.cooldownMs) || this.cooldownMs < 0)
13
+ throw new TypeError("Circuit cooldownMs must be a non-negative number");
14
+ }
15
+ getState(provider) {
16
+ const circuit = this.get(provider);
17
+ if (circuit.openUntil === 0)
18
+ return "closed";
19
+ if (this.now() < circuit.openUntil)
20
+ return "open";
21
+ return "half-open";
22
+ }
23
+ acquire(provider) {
24
+ const circuit = this.get(provider);
25
+ if (circuit.openUntil === 0)
26
+ return true;
27
+ if (this.now() < circuit.openUntil || circuit.probeInFlight)
28
+ return false;
29
+ circuit.probeInFlight = true;
30
+ return true;
31
+ }
32
+ release(provider) {
33
+ this.get(provider).probeInFlight = false;
34
+ }
35
+ recordSuccess(provider) {
36
+ const circuit = this.get(provider);
37
+ circuit.failures = 0;
38
+ circuit.openUntil = 0;
39
+ circuit.probeInFlight = false;
40
+ }
41
+ recordFailure(provider) {
42
+ const circuit = this.get(provider);
43
+ circuit.probeInFlight = false;
44
+ circuit.failures += 1;
45
+ if (circuit.failures >= this.failureThreshold) {
46
+ circuit.openUntil = this.now() + this.cooldownMs;
47
+ }
48
+ }
49
+ get(provider) {
50
+ let circuit = this.circuits.get(provider);
51
+ if (!circuit) {
52
+ circuit = { failures: 0, openUntil: 0, probeInFlight: false };
53
+ this.circuits.set(provider, circuit);
54
+ }
55
+ return circuit;
56
+ }
57
+ }
58
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/pool/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { SmsPoolAttempt, SmsPoolOperation, SmsProviderPoolOptions } from "../contracts/pool.js";
2
+ import type { SmsBatchMessage, SmsBulkMessage, SmsBulkSender, SmsBulkSendResult, SmsMessage, SmsMessageSender, SmsSendResult, SmsTemplateMessage, SmsTemplateSender } from "../contracts/sms.js";
3
+ import type { SmsIrLikeToLikeMessage } from "../contracts/sms-ir.js";
4
+ import { SmsProviderError } from "../errors/sms-error.js";
5
+ export declare class SmsProviderPoolError extends SmsProviderError {
6
+ readonly operation: SmsPoolOperation;
7
+ readonly outcome: "unknown" | "rejected" | "unavailable";
8
+ readonly attempts: readonly SmsPoolAttempt[];
9
+ constructor(message: string, options: Readonly<{
10
+ operation: SmsPoolOperation;
11
+ outcome: "unknown" | "rejected" | "unavailable";
12
+ attempts: readonly SmsPoolAttempt[];
13
+ retryable?: boolean;
14
+ code?: string;
15
+ }>);
16
+ }
17
+ export declare class SmsProviderPool implements SmsMessageSender<SmsMessage>, SmsTemplateSender<SmsTemplateMessage>, SmsBulkSender<SmsBulkMessage> {
18
+ readonly name = "sms-pool";
19
+ private readonly providers;
20
+ private readonly strategy;
21
+ private readonly health;
22
+ private readonly maxAttemptsPerProvider;
23
+ private readonly initialDelayMs;
24
+ private readonly maxDelayMs;
25
+ private readonly backoffMultiplier;
26
+ private readonly sleep;
27
+ private readonly onEvent?;
28
+ private readonly classifyError?;
29
+ private readonly observedCircuitStates;
30
+ constructor(options: SmsProviderPoolOptions);
31
+ sendMessage(message: SmsMessage): Promise<SmsSendResult>;
32
+ sendTemplate(message: SmsTemplateMessage): Promise<SmsSendResult>;
33
+ sendBulk(message: SmsBulkMessage): Promise<SmsBulkSendResult>;
34
+ sendArray(messages: readonly SmsBatchMessage[], options?: Readonly<{
35
+ signal?: AbortSignal;
36
+ }>): Promise<readonly SmsSendResult[]>;
37
+ sendLikeToLike(message: SmsIrLikeToLikeMessage): Promise<SmsBulkSendResult>;
38
+ private execute;
39
+ private classify;
40
+ private updateHealth;
41
+ private observeCircuitState;
42
+ private emit;
43
+ private abortError;
44
+ private waitBeforeRetry;
45
+ }
46
+ //# sourceMappingURL=sms-provider-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sms-provider-pool.d.ts","sourceRoot":"","sources":["../../src/pool/sms-provider-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,cAAc,EAGd,gBAAgB,EAEhB,sBAAsB,EAEtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACX,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAsB,MAAM,wBAAwB,CAAC;AAI9E,qBAAa,oBAAqB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAE7C,YACC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,QAAQ,CAAC;QACjB,SAAS,EAAE,gBAAgB,CAAC;QAC5B,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;QAChD,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;QACpC,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;KACd,CAAC,EAgBF;CACD;AAED,qBAAa,eACZ,YACC,gBAAgB,CAAC,UAAU,CAAC,EAC5B,iBAAiB,CAAC,kBAAkB,CAAC,EACrC,aAAa,CAAC,cAAc,CAAC;IAE9B,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkD;IAC3E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgD;IACvE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+C;IACrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAgC;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA0C;IACzE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAGlC;IAEJ,YAAY,OAAO,EAAE,sBAAsB,EAmD1C;IAEK,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAK7D;IAEK,YAAY,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAKtE;IAEK,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAKlE;IAEK,SAAS,CACd,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,OAAO,GAAE,QAAQ,CAAC;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,CAAM,GAC9C,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAKnC;IAEK,cAAc,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAKhF;YAEa,OAAO;IAmJrB,OAAO,CAAC,QAAQ;IAqBhB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,UAAU;YAeJ,eAAe;CAe7B"}