@parsrun/sms 0.2.1
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 +133 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +457 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/console.d.ts +65 -0
- package/dist/providers/console.js +77 -0
- package/dist/providers/console.js.map +1 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +284 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/netgsm.d.ts +89 -0
- package/dist/providers/netgsm.js +210 -0
- package/dist/providers/netgsm.js.map +1 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var SMSErrorCodes = {
|
|
3
|
+
INVALID_CONFIG: "SMS_INVALID_CONFIG",
|
|
4
|
+
SEND_FAILED: "SMS_SEND_FAILED",
|
|
5
|
+
INVALID_PHONE: "SMS_INVALID_PHONE",
|
|
6
|
+
RATE_LIMITED: "SMS_RATE_LIMITED",
|
|
7
|
+
INSUFFICIENT_BALANCE: "SMS_INSUFFICIENT_BALANCE",
|
|
8
|
+
PROVIDER_ERROR: "SMS_PROVIDER_ERROR"
|
|
9
|
+
};
|
|
10
|
+
var SMSError = class extends Error {
|
|
11
|
+
code;
|
|
12
|
+
cause;
|
|
13
|
+
constructor(message, code, cause) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "SMSError";
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.cause = cause;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/providers/netgsm.ts
|
|
22
|
+
var NetGSMProvider = class {
|
|
23
|
+
/** Provider type identifier */
|
|
24
|
+
type = "netgsm";
|
|
25
|
+
username;
|
|
26
|
+
password;
|
|
27
|
+
from;
|
|
28
|
+
baseUrl;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new NetGSMProvider instance.
|
|
31
|
+
*
|
|
32
|
+
* @param config - The provider configuration including credentials and sender info
|
|
33
|
+
*/
|
|
34
|
+
constructor(config) {
|
|
35
|
+
if (!config.username || !config.password) {
|
|
36
|
+
throw new SMSError(
|
|
37
|
+
"NetGSM requires username and password",
|
|
38
|
+
SMSErrorCodes.INVALID_CONFIG
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (!config.from) {
|
|
42
|
+
throw new SMSError(
|
|
43
|
+
"NetGSM requires a sender ID (from/header)",
|
|
44
|
+
SMSErrorCodes.INVALID_CONFIG
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
this.username = config.username;
|
|
48
|
+
this.password = config.password;
|
|
49
|
+
this.from = config.from;
|
|
50
|
+
this.baseUrl = config.providerUrl || "https://api.netgsm.com.tr/sms/send/otp";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sends an SMS via the NetGSM API.
|
|
54
|
+
*
|
|
55
|
+
* @param options - The SMS options including recipient and message
|
|
56
|
+
* @returns A promise that resolves to the send result
|
|
57
|
+
*/
|
|
58
|
+
async send(options) {
|
|
59
|
+
const from = options.from || this.from;
|
|
60
|
+
const to = this.sanitizePhoneNumber(options.to);
|
|
61
|
+
const xmlData = `<?xml version='1.0' encoding='iso-8859-9'?>
|
|
62
|
+
<mainbody>
|
|
63
|
+
<header>
|
|
64
|
+
<usercode>${this.escapeXml(this.username)}</usercode>
|
|
65
|
+
<password>${this.escapeXml(this.password)}</password>
|
|
66
|
+
<msgheader>${this.escapeXml(from)}</msgheader>
|
|
67
|
+
<encoding>TR</encoding>
|
|
68
|
+
</header>
|
|
69
|
+
<body>
|
|
70
|
+
<msg><![CDATA[${options.message}]]></msg>
|
|
71
|
+
<no>${to}</no>
|
|
72
|
+
</body>
|
|
73
|
+
</mainbody>`;
|
|
74
|
+
try {
|
|
75
|
+
const response = await fetch(this.baseUrl, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: {
|
|
78
|
+
"Content-Type": "application/xml"
|
|
79
|
+
},
|
|
80
|
+
body: xmlData
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const responseText = await response.text();
|
|
89
|
+
const result = this.parseResponse(responseText);
|
|
90
|
+
if (result.success && result.code) {
|
|
91
|
+
const successResult = {
|
|
92
|
+
success: true,
|
|
93
|
+
messageId: result.code,
|
|
94
|
+
data: { raw: responseText }
|
|
95
|
+
};
|
|
96
|
+
return successResult;
|
|
97
|
+
}
|
|
98
|
+
const errorResult = {
|
|
99
|
+
success: false,
|
|
100
|
+
error: this.getErrorMessage(result.code),
|
|
101
|
+
data: { code: result.code, raw: responseText }
|
|
102
|
+
};
|
|
103
|
+
return errorResult;
|
|
104
|
+
} catch (err) {
|
|
105
|
+
throw new SMSError(
|
|
106
|
+
`NetGSM send failed: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
107
|
+
SMSErrorCodes.SEND_FAILED,
|
|
108
|
+
err
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Sends multiple SMS messages sequentially.
|
|
114
|
+
*
|
|
115
|
+
* @param options - The batch SMS options
|
|
116
|
+
* @returns A promise that resolves to the batch result
|
|
117
|
+
*/
|
|
118
|
+
async sendBatch(options) {
|
|
119
|
+
const results = [];
|
|
120
|
+
let successful = 0;
|
|
121
|
+
let failed = 0;
|
|
122
|
+
for (const sms of options.messages) {
|
|
123
|
+
try {
|
|
124
|
+
const result = await this.send(sms);
|
|
125
|
+
results.push(result);
|
|
126
|
+
if (result.success) {
|
|
127
|
+
successful++;
|
|
128
|
+
} else {
|
|
129
|
+
failed++;
|
|
130
|
+
if (options.stopOnError) break;
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
failed++;
|
|
134
|
+
results.push({
|
|
135
|
+
success: false,
|
|
136
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
137
|
+
});
|
|
138
|
+
if (options.stopOnError) break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
total: options.messages.length,
|
|
143
|
+
successful,
|
|
144
|
+
failed,
|
|
145
|
+
results
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Verifies the NetGSM credentials by checking balance/credit.
|
|
150
|
+
*
|
|
151
|
+
* @returns A promise that resolves to true if credentials are valid
|
|
152
|
+
*/
|
|
153
|
+
async verify() {
|
|
154
|
+
return !!(this.username && this.password && this.from);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Parse NetGSM XML response
|
|
158
|
+
* Success codes: "0", "00", or numeric job ID
|
|
159
|
+
*/
|
|
160
|
+
parseResponse(xml) {
|
|
161
|
+
try {
|
|
162
|
+
const codeMatch = xml.match(/<code>(.*?)<\/code>/);
|
|
163
|
+
if (codeMatch && codeMatch[1]) {
|
|
164
|
+
const code = codeMatch[1].trim();
|
|
165
|
+
if (code === "00" || code === "0") {
|
|
166
|
+
return { success: true, code };
|
|
167
|
+
}
|
|
168
|
+
return { success: false, code };
|
|
169
|
+
}
|
|
170
|
+
const trimmed = xml.trim();
|
|
171
|
+
if (/^\d+$/.test(trimmed) && trimmed.length > 5) {
|
|
172
|
+
return { success: true, code: trimmed };
|
|
173
|
+
}
|
|
174
|
+
return { success: false };
|
|
175
|
+
} catch {
|
|
176
|
+
return { success: false };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get human-readable error message for NetGSM error codes
|
|
181
|
+
*/
|
|
182
|
+
getErrorMessage(code) {
|
|
183
|
+
const errorMessages = {
|
|
184
|
+
"20": "Mesaj metninde hata var",
|
|
185
|
+
"30": "Ge\xE7ersiz kullan\u0131c\u0131 ad\u0131 veya \u015Fifre",
|
|
186
|
+
"40": "Mesaj ba\u015Fl\u0131\u011F\u0131 sistemde tan\u0131ml\u0131 de\u011Fil",
|
|
187
|
+
"50": "Abone hesab\u0131 tan\u0131ml\u0131 de\u011Fil",
|
|
188
|
+
"51": "Abone hesab\u0131nda yeterli bakiye yok",
|
|
189
|
+
"60": "G\xF6nderilecek mesaj bulunamad\u0131",
|
|
190
|
+
"70": "Ge\xE7ersiz parametre hatas\u0131",
|
|
191
|
+
"80": "G\xF6nderim zamanlamas\u0131 hatal\u0131",
|
|
192
|
+
"85": "G\xF6nderim zamanlamas\u0131 \xE7ok ge\xE7"
|
|
193
|
+
};
|
|
194
|
+
return code ? errorMessages[code] || `NetGSM error code: ${code}` : "Unknown error";
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Escape XML special characters
|
|
198
|
+
*/
|
|
199
|
+
escapeXml(unsafe) {
|
|
200
|
+
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Sanitize phone number (remove spaces, dashes, parentheses)
|
|
204
|
+
*/
|
|
205
|
+
sanitizePhoneNumber(phone) {
|
|
206
|
+
return phone.replace(/[\s\-\(\)\+]/g, "");
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
function createNetGSMProvider(config) {
|
|
210
|
+
return new NetGSMProvider(config);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/providers/console.ts
|
|
214
|
+
var ConsoleProvider = class {
|
|
215
|
+
/** Provider type identifier */
|
|
216
|
+
type = "console";
|
|
217
|
+
from;
|
|
218
|
+
delay;
|
|
219
|
+
/**
|
|
220
|
+
* Creates a new ConsoleProvider instance.
|
|
221
|
+
*
|
|
222
|
+
* @param config - The provider configuration
|
|
223
|
+
*/
|
|
224
|
+
constructor(config) {
|
|
225
|
+
this.from = config.from || "CONSOLE";
|
|
226
|
+
this.delay = config.delay ?? 100;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Logs an SMS message to the console.
|
|
230
|
+
*
|
|
231
|
+
* @param options - The SMS options
|
|
232
|
+
* @returns A promise that resolves to a successful result
|
|
233
|
+
*/
|
|
234
|
+
async send(options) {
|
|
235
|
+
if (this.delay > 0) {
|
|
236
|
+
await new Promise((resolve) => setTimeout(resolve, this.delay));
|
|
237
|
+
}
|
|
238
|
+
const from = options.from || this.from;
|
|
239
|
+
const messageId = `console-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
240
|
+
console.log("\n" + "\u2500".repeat(50));
|
|
241
|
+
console.log("\u{1F4F1} SMS (Console Provider)");
|
|
242
|
+
console.log("\u2500".repeat(50));
|
|
243
|
+
console.log(`To: ${options.to}`);
|
|
244
|
+
console.log(`From: ${from}`);
|
|
245
|
+
console.log(`Message: ${options.message}`);
|
|
246
|
+
if (options.tags) {
|
|
247
|
+
console.log(`Tags: ${JSON.stringify(options.tags)}`);
|
|
248
|
+
}
|
|
249
|
+
console.log(`ID: ${messageId}`);
|
|
250
|
+
console.log("\u2500".repeat(50) + "\n");
|
|
251
|
+
return {
|
|
252
|
+
success: true,
|
|
253
|
+
messageId,
|
|
254
|
+
data: { provider: "console", logged: true }
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Logs multiple SMS messages to the console.
|
|
259
|
+
*
|
|
260
|
+
* @param options - The batch SMS options
|
|
261
|
+
* @returns A promise that resolves to the batch result
|
|
262
|
+
*/
|
|
263
|
+
async sendBatch(options) {
|
|
264
|
+
const results = [];
|
|
265
|
+
for (const sms of options.messages) {
|
|
266
|
+
const result = await this.send(sms);
|
|
267
|
+
results.push(result);
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
total: options.messages.length,
|
|
271
|
+
successful: options.messages.length,
|
|
272
|
+
failed: 0,
|
|
273
|
+
results
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Always returns true for console provider.
|
|
278
|
+
*/
|
|
279
|
+
async verify() {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
function createConsoleProvider(config) {
|
|
284
|
+
return new ConsoleProvider(config || {});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// src/index.ts
|
|
288
|
+
var SMSService = class {
|
|
289
|
+
provider;
|
|
290
|
+
debug;
|
|
291
|
+
/**
|
|
292
|
+
* Creates a new SMSService instance.
|
|
293
|
+
*
|
|
294
|
+
* @param config - The SMS service configuration
|
|
295
|
+
*/
|
|
296
|
+
constructor(config) {
|
|
297
|
+
this.debug = config.debug ?? false;
|
|
298
|
+
this.provider = this.createProvider(config);
|
|
299
|
+
}
|
|
300
|
+
createProvider(config) {
|
|
301
|
+
const providerConfig = {};
|
|
302
|
+
if (config.apiKey !== void 0) providerConfig.apiKey = config.apiKey;
|
|
303
|
+
if (config.username !== void 0) providerConfig.username = config.username;
|
|
304
|
+
if (config.password !== void 0) providerConfig.password = config.password;
|
|
305
|
+
if (config.from !== void 0) providerConfig.from = config.from;
|
|
306
|
+
if (config.options !== void 0) providerConfig.options = config.options;
|
|
307
|
+
if (config.providerUrl !== void 0) providerConfig.providerUrl = config.providerUrl;
|
|
308
|
+
switch (config.provider) {
|
|
309
|
+
case "netgsm":
|
|
310
|
+
return new NetGSMProvider(providerConfig);
|
|
311
|
+
case "console":
|
|
312
|
+
return new ConsoleProvider(providerConfig);
|
|
313
|
+
default:
|
|
314
|
+
throw new SMSError(
|
|
315
|
+
`Unknown SMS provider: ${config.provider}`,
|
|
316
|
+
SMSErrorCodes.INVALID_CONFIG
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Gets the type of SMS provider being used.
|
|
322
|
+
*/
|
|
323
|
+
get providerType() {
|
|
324
|
+
return this.provider.type;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Sends a single SMS message.
|
|
328
|
+
*
|
|
329
|
+
* @param options - The SMS options
|
|
330
|
+
* @returns A promise that resolves to the send result
|
|
331
|
+
*/
|
|
332
|
+
async send(options) {
|
|
333
|
+
if (this.debug) {
|
|
334
|
+
console.log("[SMS] Sending:", {
|
|
335
|
+
to: options.to,
|
|
336
|
+
message: options.message.slice(0, 50) + (options.message.length > 50 ? "..." : ""),
|
|
337
|
+
provider: this.provider.type
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
const result = await this.provider.send(options);
|
|
341
|
+
if (this.debug) {
|
|
342
|
+
console.log("[SMS] Result:", result);
|
|
343
|
+
}
|
|
344
|
+
return result;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Sends multiple SMS messages in a batch.
|
|
348
|
+
*
|
|
349
|
+
* @param options - The batch SMS options
|
|
350
|
+
* @returns A promise that resolves to the batch result
|
|
351
|
+
*/
|
|
352
|
+
async sendBatch(options) {
|
|
353
|
+
if (this.debug) {
|
|
354
|
+
console.log("[SMS] Sending batch:", {
|
|
355
|
+
count: options.messages.length,
|
|
356
|
+
provider: this.provider.type
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
if (this.provider.sendBatch) {
|
|
360
|
+
const result = await this.provider.sendBatch(options);
|
|
361
|
+
if (this.debug) {
|
|
362
|
+
console.log("[SMS] Batch result:", {
|
|
363
|
+
total: result.total,
|
|
364
|
+
successful: result.successful,
|
|
365
|
+
failed: result.failed
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
const results = [];
|
|
371
|
+
let successful = 0;
|
|
372
|
+
let failed = 0;
|
|
373
|
+
for (const sms of options.messages) {
|
|
374
|
+
try {
|
|
375
|
+
const result = await this.send(sms);
|
|
376
|
+
results.push(result);
|
|
377
|
+
if (result.success) {
|
|
378
|
+
successful++;
|
|
379
|
+
} else {
|
|
380
|
+
failed++;
|
|
381
|
+
if (options.stopOnError) break;
|
|
382
|
+
}
|
|
383
|
+
} catch (err) {
|
|
384
|
+
failed++;
|
|
385
|
+
results.push({
|
|
386
|
+
success: false,
|
|
387
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
388
|
+
});
|
|
389
|
+
if (options.stopOnError) break;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
total: options.messages.length,
|
|
394
|
+
successful,
|
|
395
|
+
failed,
|
|
396
|
+
results
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Verifies the provider configuration.
|
|
401
|
+
*
|
|
402
|
+
* @returns A promise that resolves to true if configuration is valid
|
|
403
|
+
*/
|
|
404
|
+
async verify() {
|
|
405
|
+
if (this.provider.verify) {
|
|
406
|
+
return this.provider.verify();
|
|
407
|
+
}
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Send OTP verification SMS
|
|
412
|
+
*
|
|
413
|
+
* @param phone - Recipient phone number
|
|
414
|
+
* @param code - OTP code
|
|
415
|
+
* @param expiresInMinutes - Code expiration time
|
|
416
|
+
*/
|
|
417
|
+
async sendOTP(phone, code, expiresInMinutes = 10) {
|
|
418
|
+
const message = `Dogrulama kodunuz: ${code}. Bu kod ${expiresInMinutes} dakika gecerlidir.`;
|
|
419
|
+
return this.send({ to: phone, message });
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Send welcome SMS
|
|
423
|
+
*
|
|
424
|
+
* @param phone - Recipient phone number
|
|
425
|
+
* @param name - User's display name
|
|
426
|
+
*/
|
|
427
|
+
async sendWelcome(phone, name) {
|
|
428
|
+
const displayName = name || "Kullanici";
|
|
429
|
+
const message = `Merhaba ${displayName}! Hesabiniz basariyla olusturuldu.`;
|
|
430
|
+
return this.send({ to: phone, message });
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
function createSMSService(config) {
|
|
434
|
+
return new SMSService(config);
|
|
435
|
+
}
|
|
436
|
+
function createSMSProvider(type, config) {
|
|
437
|
+
switch (type) {
|
|
438
|
+
case "netgsm":
|
|
439
|
+
return new NetGSMProvider(config);
|
|
440
|
+
case "console":
|
|
441
|
+
return new ConsoleProvider(config);
|
|
442
|
+
default:
|
|
443
|
+
throw new SMSError(
|
|
444
|
+
`Unknown SMS provider: ${type}`,
|
|
445
|
+
SMSErrorCodes.INVALID_CONFIG
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
var index_default = {
|
|
450
|
+
SMSService,
|
|
451
|
+
createSMSService,
|
|
452
|
+
createSMSProvider
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
export { ConsoleProvider, NetGSMProvider, SMSError, SMSErrorCodes, SMSService, createConsoleProvider, createNetGSMProvider, createSMSProvider, createSMSService, index_default as default };
|
|
456
|
+
//# sourceMappingURL=index.js.map
|
|
457
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/providers/netgsm.ts","../src/providers/console.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @parsrun/sms - Type definitions\n */\n\n/**\n * Supported SMS provider types\n */\nexport type SMSProviderType = \"netgsm\" | \"twilio\" | \"console\";\n\n/**\n * SMS send options\n */\nexport interface SMSOptions {\n /** Recipient phone number (international format recommended, e.g., 905xxxxxxxxx) */\n to: string;\n /** SMS message content */\n message: string;\n /** Optional sender ID override */\n from?: string;\n /** Optional metadata/tags */\n tags?: Record<string, string>;\n}\n\n/**\n * SMS send result\n */\nexport interface SMSResult {\n /** Whether the SMS was sent successfully */\n success: boolean;\n /** Provider-specific message ID */\n messageId?: string;\n /** Error message if send failed */\n error?: string;\n /** Raw provider response data */\n data?: unknown;\n}\n\n/**\n * Batch SMS options\n */\nexport interface BatchSMSOptions {\n /** Array of SMS messages to send */\n messages: SMSOptions[];\n /** Stop sending if an error occurs */\n stopOnError?: boolean;\n}\n\n/**\n * Batch SMS result\n */\nexport interface BatchSMSResult {\n /** Total number of messages attempted */\n total: number;\n /** Number of successfully sent messages */\n successful: number;\n /** Number of failed messages */\n failed: number;\n /** Individual results for each message */\n results: SMSResult[];\n}\n\n/**\n * SMS provider configuration\n */\nexport interface SMSProviderConfig {\n /** API key or authentication token */\n apiKey?: string;\n /** Provider username (for providers like NetGSM) */\n username?: string;\n /** Provider password (for providers like NetGSM) */\n password?: string;\n /** Default sender ID/header */\n from?: string;\n /** Provider-specific options */\n options?: Record<string, unknown>;\n}\n\n/**\n * SMS service configuration\n */\nexport interface SMSServiceConfig extends SMSProviderConfig {\n /** SMS provider type */\n provider: SMSProviderType;\n /** Provider API URL (for custom endpoints) */\n providerUrl?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * SMS provider interface\n */\nexport interface SMSProvider {\n /** Provider type identifier */\n readonly type: SMSProviderType;\n\n /** Send a single SMS */\n send(options: SMSOptions): Promise<SMSResult>;\n\n /** Send multiple SMS messages (optional) */\n sendBatch?(options: BatchSMSOptions): Promise<BatchSMSResult>;\n\n /** Verify provider configuration (optional) */\n verify?(): Promise<boolean>;\n}\n\n/**\n * SMS error codes\n */\nexport const SMSErrorCodes = {\n INVALID_CONFIG: \"SMS_INVALID_CONFIG\",\n SEND_FAILED: \"SMS_SEND_FAILED\",\n INVALID_PHONE: \"SMS_INVALID_PHONE\",\n RATE_LIMITED: \"SMS_RATE_LIMITED\",\n INSUFFICIENT_BALANCE: \"SMS_INSUFFICIENT_BALANCE\",\n PROVIDER_ERROR: \"SMS_PROVIDER_ERROR\",\n} as const;\n\nexport type SMSErrorCode = (typeof SMSErrorCodes)[keyof typeof SMSErrorCodes];\n\n/**\n * SMS error class\n */\nexport class SMSError extends Error {\n code: SMSErrorCode;\n cause?: unknown;\n\n constructor(message: string, code: SMSErrorCode, cause?: unknown) {\n super(message);\n this.name = \"SMSError\";\n this.code = code;\n this.cause = cause;\n }\n}\n","/**\n * @parsrun/sms - NetGSM Provider\n * Edge-compatible NetGSM SMS provider using fetch API\n */\n\nimport type {\n BatchSMSOptions,\n BatchSMSResult,\n SMSOptions,\n SMSProvider,\n SMSProviderConfig,\n SMSResult,\n} from \"../types.js\";\nimport { SMSError, SMSErrorCodes } from \"../types.js\";\n\n/**\n * NetGSM SMS Provider\n * Uses fetch API for edge compatibility\n *\n * @example\n * ```typescript\n * const netgsm = new NetGSMProvider({\n * username: process.env.NETGSM_USERNAME,\n * password: process.env.NETGSM_PASSWORD,\n * from: 'MYSENDER',\n * });\n *\n * await netgsm.send({\n * to: '905551234567',\n * message: 'Hello from Pars!',\n * });\n * ```\n */\nexport class NetGSMProvider implements SMSProvider {\n /** Provider type identifier */\n readonly type = \"netgsm\" as const;\n\n private username: string;\n private password: string;\n private from: string;\n private baseUrl: string;\n\n /**\n * Creates a new NetGSMProvider instance.\n *\n * @param config - The provider configuration including credentials and sender info\n */\n constructor(config: SMSProviderConfig & { providerUrl?: string }) {\n if (!config.username || !config.password) {\n throw new SMSError(\n \"NetGSM requires username and password\",\n SMSErrorCodes.INVALID_CONFIG\n );\n }\n if (!config.from) {\n throw new SMSError(\n \"NetGSM requires a sender ID (from/header)\",\n SMSErrorCodes.INVALID_CONFIG\n );\n }\n\n this.username = config.username;\n this.password = config.password;\n this.from = config.from;\n this.baseUrl = config.providerUrl || \"https://api.netgsm.com.tr/sms/send/otp\";\n }\n\n /**\n * Sends an SMS via the NetGSM API.\n *\n * @param options - The SMS options including recipient and message\n * @returns A promise that resolves to the send result\n */\n async send(options: SMSOptions): Promise<SMSResult> {\n const from = options.from || this.from;\n const to = this.sanitizePhoneNumber(options.to);\n\n const xmlData = `<?xml version='1.0' encoding='iso-8859-9'?>\n<mainbody>\n <header>\n <usercode>${this.escapeXml(this.username)}</usercode>\n <password>${this.escapeXml(this.password)}</password>\n <msgheader>${this.escapeXml(from)}</msgheader>\n <encoding>TR</encoding>\n </header>\n <body>\n <msg><![CDATA[${options.message}]]></msg>\n <no>${to}</no>\n </body>\n</mainbody>`;\n\n try {\n const response = await fetch(this.baseUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/xml\",\n },\n body: xmlData,\n });\n\n if (!response.ok) {\n return {\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n const responseText = await response.text();\n const result = this.parseResponse(responseText);\n\n if (result.success && result.code) {\n const successResult: SMSResult = {\n success: true,\n messageId: result.code,\n data: { raw: responseText },\n };\n return successResult;\n }\n\n const errorResult: SMSResult = {\n success: false,\n error: this.getErrorMessage(result.code),\n data: { code: result.code, raw: responseText },\n };\n return errorResult;\n } catch (err) {\n throw new SMSError(\n `NetGSM send failed: ${err instanceof Error ? err.message : \"Unknown error\"}`,\n SMSErrorCodes.SEND_FAILED,\n err\n );\n }\n }\n\n /**\n * Sends multiple SMS messages sequentially.\n *\n * @param options - The batch SMS options\n * @returns A promise that resolves to the batch result\n */\n async sendBatch(options: BatchSMSOptions): Promise<BatchSMSResult> {\n const results: SMSResult[] = [];\n let successful = 0;\n let failed = 0;\n\n for (const sms of options.messages) {\n try {\n const result = await this.send(sms);\n results.push(result);\n\n if (result.success) {\n successful++;\n } else {\n failed++;\n if (options.stopOnError) break;\n }\n } catch (err) {\n failed++;\n results.push({\n success: false,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n\n if (options.stopOnError) break;\n }\n }\n\n return {\n total: options.messages.length,\n successful,\n failed,\n results,\n };\n }\n\n /**\n * Verifies the NetGSM credentials by checking balance/credit.\n *\n * @returns A promise that resolves to true if credentials are valid\n */\n async verify(): Promise<boolean> {\n // NetGSM doesn't have a dedicated verify endpoint,\n // so we just return true if config is valid\n return !!(this.username && this.password && this.from);\n }\n\n /**\n * Parse NetGSM XML response\n * Success codes: \"0\", \"00\", or numeric job ID\n */\n private parseResponse(xml: string): { success: boolean; code?: string } {\n try {\n // Try to find <code> element\n const codeMatch = xml.match(/<code>(.*?)<\\/code>/);\n if (codeMatch && codeMatch[1]) {\n const code = codeMatch[1].trim();\n // NetGSM returns \"00\" or \"0\" for success\n if (code === \"00\" || code === \"0\") {\n return { success: true, code };\n }\n return { success: false, code };\n }\n\n // If no <code> element, check for numeric job ID (success)\n const trimmed = xml.trim();\n if (/^\\d+$/.test(trimmed) && trimmed.length > 5) {\n return { success: true, code: trimmed };\n }\n\n return { success: false };\n } catch {\n return { success: false };\n }\n }\n\n /**\n * Get human-readable error message for NetGSM error codes\n */\n private getErrorMessage(code?: string): string {\n const errorMessages: Record<string, string> = {\n \"20\": \"Mesaj metninde hata var\",\n \"30\": \"Geçersiz kullanıcı adı veya şifre\",\n \"40\": \"Mesaj başlığı sistemde tanımlı değil\",\n \"50\": \"Abone hesabı tanımlı değil\",\n \"51\": \"Abone hesabında yeterli bakiye yok\",\n \"60\": \"Gönderilecek mesaj bulunamadı\",\n \"70\": \"Geçersiz parametre hatası\",\n \"80\": \"Gönderim zamanlaması hatalı\",\n \"85\": \"Gönderim zamanlaması çok geç\",\n };\n\n return code ? errorMessages[code] || `NetGSM error code: ${code}` : \"Unknown error\";\n }\n\n /**\n * Escape XML special characters\n */\n private escapeXml(unsafe: string): string {\n return unsafe\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n }\n\n /**\n * Sanitize phone number (remove spaces, dashes, parentheses)\n */\n private sanitizePhoneNumber(phone: string): string {\n return phone.replace(/[\\s\\-\\(\\)\\+]/g, \"\");\n }\n}\n\n/**\n * Creates a NetGSM provider instance.\n *\n * @param config - The provider configuration\n * @returns A new NetGSMProvider instance\n */\nexport function createNetGSMProvider(\n config: SMSProviderConfig & { providerUrl?: string }\n): NetGSMProvider {\n return new NetGSMProvider(config);\n}\n","/**\n * @parsrun/sms - Console Provider\n * Development provider that logs SMS to console instead of sending\n */\n\nimport type {\n BatchSMSOptions,\n BatchSMSResult,\n SMSOptions,\n SMSProvider,\n SMSProviderConfig,\n SMSResult,\n} from \"../types.js\";\n\n/**\n * Console SMS Provider\n * Logs SMS messages to console for development/testing\n *\n * @example\n * ```typescript\n * const sms = new ConsoleProvider({ from: 'TEST' });\n *\n * await sms.send({\n * to: '905551234567',\n * message: 'Test message',\n * });\n * // Logs: [SMS] To: 905551234567, From: TEST, Message: Test message\n * ```\n */\nexport class ConsoleProvider implements SMSProvider {\n /** Provider type identifier */\n readonly type = \"console\" as const;\n\n private from: string;\n private delay: number;\n\n /**\n * Creates a new ConsoleProvider instance.\n *\n * @param config - The provider configuration\n */\n constructor(config: SMSProviderConfig & { delay?: number }) {\n this.from = config.from || \"CONSOLE\";\n this.delay = config.delay ?? 100; // Simulate network delay\n }\n\n /**\n * Logs an SMS message to the console.\n *\n * @param options - The SMS options\n * @returns A promise that resolves to a successful result\n */\n async send(options: SMSOptions): Promise<SMSResult> {\n // Simulate network delay\n if (this.delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.delay));\n }\n\n const from = options.from || this.from;\n const messageId = `console-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n\n console.log(\"\\n\" + \"─\".repeat(50));\n console.log(\"📱 SMS (Console Provider)\");\n console.log(\"─\".repeat(50));\n console.log(`To: ${options.to}`);\n console.log(`From: ${from}`);\n console.log(`Message: ${options.message}`);\n if (options.tags) {\n console.log(`Tags: ${JSON.stringify(options.tags)}`);\n }\n console.log(`ID: ${messageId}`);\n console.log(\"─\".repeat(50) + \"\\n\");\n\n return {\n success: true,\n messageId,\n data: { provider: \"console\", logged: true },\n };\n }\n\n /**\n * Logs multiple SMS messages to the console.\n *\n * @param options - The batch SMS options\n * @returns A promise that resolves to the batch result\n */\n async sendBatch(options: BatchSMSOptions): Promise<BatchSMSResult> {\n const results: SMSResult[] = [];\n\n for (const sms of options.messages) {\n const result = await this.send(sms);\n results.push(result);\n }\n\n return {\n total: options.messages.length,\n successful: options.messages.length,\n failed: 0,\n results,\n };\n }\n\n /**\n * Always returns true for console provider.\n */\n async verify(): Promise<boolean> {\n return true;\n }\n}\n\n/**\n * Creates a Console provider instance.\n *\n * @param config - The provider configuration\n * @returns A new ConsoleProvider instance\n */\nexport function createConsoleProvider(\n config?: SMSProviderConfig & { delay?: number }\n): ConsoleProvider {\n return new ConsoleProvider(config || {});\n}\n","/**\n * @module\n * Edge-compatible SMS sending for Pars.\n *\n * Supports multiple providers:\n * - NetGSM (Turkey)\n * - Console (development)\n *\n * @example\n * ```typescript\n * import { createSMSService } from '@parsrun/sms';\n *\n * const sms = createSMSService({\n * provider: 'netgsm',\n * username: process.env.NETGSM_USERNAME,\n * password: process.env.NETGSM_PASSWORD,\n * from: 'MYSENDER',\n * });\n *\n * await sms.send({\n * to: '905551234567',\n * message: 'Your verification code is: 123456',\n * });\n * ```\n */\n\n// Re-export types\nexport * from \"./types.js\";\n\n// Re-export providers\nexport { NetGSMProvider, createNetGSMProvider } from \"./providers/netgsm.js\";\nexport { ConsoleProvider, createConsoleProvider } from \"./providers/console.js\";\n\nimport type {\n BatchSMSOptions,\n BatchSMSResult,\n SMSOptions,\n SMSProvider,\n SMSProviderConfig,\n SMSProviderType,\n SMSResult,\n SMSServiceConfig,\n} from \"./types.js\";\nimport { SMSError, SMSErrorCodes } from \"./types.js\";\nimport { NetGSMProvider } from \"./providers/netgsm.js\";\nimport { ConsoleProvider } from \"./providers/console.js\";\n\n/**\n * SMS Service\n *\n * High-level SMS service that provides a unified interface for sending SMS\n * through various providers (NetGSM, Twilio, or Console for development).\n *\n * @example\n * ```typescript\n * const service = new SMSService({\n * provider: 'netgsm',\n * username: 'your-username',\n * password: 'your-password',\n * from: 'MYSENDER',\n * });\n *\n * await service.send({\n * to: '905551234567',\n * message: 'Hello!',\n * });\n * ```\n */\nexport class SMSService {\n private provider: SMSProvider;\n private debug: boolean;\n\n /**\n * Creates a new SMSService instance.\n *\n * @param config - The SMS service configuration\n */\n constructor(config: SMSServiceConfig) {\n this.debug = config.debug ?? false;\n this.provider = this.createProvider(config);\n }\n\n private createProvider(config: SMSServiceConfig): SMSProvider {\n // Build config object conditionally to satisfy exactOptionalPropertyTypes\n const providerConfig: SMSProviderConfig & { providerUrl?: string } = {};\n if (config.apiKey !== undefined) providerConfig.apiKey = config.apiKey;\n if (config.username !== undefined) providerConfig.username = config.username;\n if (config.password !== undefined) providerConfig.password = config.password;\n if (config.from !== undefined) providerConfig.from = config.from;\n if (config.options !== undefined) providerConfig.options = config.options;\n if (config.providerUrl !== undefined) providerConfig.providerUrl = config.providerUrl;\n\n switch (config.provider) {\n case \"netgsm\":\n return new NetGSMProvider(providerConfig);\n case \"console\":\n return new ConsoleProvider(providerConfig);\n default:\n throw new SMSError(\n `Unknown SMS provider: ${config.provider}`,\n SMSErrorCodes.INVALID_CONFIG\n );\n }\n }\n\n /**\n * Gets the type of SMS provider being used.\n */\n get providerType(): SMSProviderType {\n return this.provider.type;\n }\n\n /**\n * Sends a single SMS message.\n *\n * @param options - The SMS options\n * @returns A promise that resolves to the send result\n */\n async send(options: SMSOptions): Promise<SMSResult> {\n if (this.debug) {\n console.log(\"[SMS] Sending:\", {\n to: options.to,\n message: options.message.slice(0, 50) + (options.message.length > 50 ? \"...\" : \"\"),\n provider: this.provider.type,\n });\n }\n\n const result = await this.provider.send(options);\n\n if (this.debug) {\n console.log(\"[SMS] Result:\", result);\n }\n\n return result;\n }\n\n /**\n * Sends multiple SMS messages in a batch.\n *\n * @param options - The batch SMS options\n * @returns A promise that resolves to the batch result\n */\n async sendBatch(options: BatchSMSOptions): Promise<BatchSMSResult> {\n if (this.debug) {\n console.log(\"[SMS] Sending batch:\", {\n count: options.messages.length,\n provider: this.provider.type,\n });\n }\n\n // Use provider's native batch if available\n if (this.provider.sendBatch) {\n const result = await this.provider.sendBatch(options);\n\n if (this.debug) {\n console.log(\"[SMS] Batch result:\", {\n total: result.total,\n successful: result.successful,\n failed: result.failed,\n });\n }\n\n return result;\n }\n\n // Fallback to sequential sending\n const results: SMSResult[] = [];\n let successful = 0;\n let failed = 0;\n\n for (const sms of options.messages) {\n try {\n const result = await this.send(sms);\n results.push(result);\n\n if (result.success) {\n successful++;\n } else {\n failed++;\n if (options.stopOnError) break;\n }\n } catch (err) {\n failed++;\n results.push({\n success: false,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n\n if (options.stopOnError) break;\n }\n }\n\n return {\n total: options.messages.length,\n successful,\n failed,\n results,\n };\n }\n\n /**\n * Verifies the provider configuration.\n *\n * @returns A promise that resolves to true if configuration is valid\n */\n async verify(): Promise<boolean> {\n if (this.provider.verify) {\n return this.provider.verify();\n }\n return true;\n }\n\n /**\n * Send OTP verification SMS\n *\n * @param phone - Recipient phone number\n * @param code - OTP code\n * @param expiresInMinutes - Code expiration time\n */\n async sendOTP(\n phone: string,\n code: string,\n expiresInMinutes = 10\n ): Promise<SMSResult> {\n const message = `Dogrulama kodunuz: ${code}. Bu kod ${expiresInMinutes} dakika gecerlidir.`;\n return this.send({ to: phone, message });\n }\n\n /**\n * Send welcome SMS\n *\n * @param phone - Recipient phone number\n * @param name - User's display name\n */\n async sendWelcome(phone: string, name?: string): Promise<SMSResult> {\n const displayName = name || \"Kullanici\";\n const message = `Merhaba ${displayName}! Hesabiniz basariyla olusturuldu.`;\n return this.send({ to: phone, message });\n }\n}\n\n/**\n * Create an SMS service\n *\n * @example\n * ```typescript\n * // With NetGSM\n * const sms = createSMSService({\n * provider: 'netgsm',\n * username: process.env.NETGSM_USERNAME,\n * password: process.env.NETGSM_PASSWORD,\n * from: 'MYSENDER',\n * });\n *\n * // For development\n * const sms = createSMSService({\n * provider: 'console',\n * from: 'TEST',\n * });\n * ```\n */\nexport function createSMSService(config: SMSServiceConfig): SMSService {\n return new SMSService(config);\n}\n\n/**\n * Creates an SMS provider instance directly.\n *\n * @param type - The type of SMS provider to create\n * @param config - The provider configuration\n * @returns A new SMS provider instance\n */\nexport function createSMSProvider(\n type: SMSProviderType,\n config: SMSProviderConfig & { providerUrl?: string }\n): SMSProvider {\n switch (type) {\n case \"netgsm\":\n return new NetGSMProvider(config);\n case \"console\":\n return new ConsoleProvider(config);\n default:\n throw new SMSError(\n `Unknown SMS provider: ${type}`,\n SMSErrorCodes.INVALID_CONFIG\n );\n }\n}\n\n// Default export\nexport default {\n SMSService,\n createSMSService,\n createSMSProvider,\n};\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { SMSProvider, SMSProviderConfig, SMSOptions, SMSResult, BatchSMSOptions, BatchSMSResult } from '../types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @parsrun/sms - Console Provider
|
|
5
|
+
* Development provider that logs SMS to console instead of sending
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Console SMS Provider
|
|
10
|
+
* Logs SMS messages to console for development/testing
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const sms = new ConsoleProvider({ from: 'TEST' });
|
|
15
|
+
*
|
|
16
|
+
* await sms.send({
|
|
17
|
+
* to: '905551234567',
|
|
18
|
+
* message: 'Test message',
|
|
19
|
+
* });
|
|
20
|
+
* // Logs: [SMS] To: 905551234567, From: TEST, Message: Test message
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare class ConsoleProvider implements SMSProvider {
|
|
24
|
+
/** Provider type identifier */
|
|
25
|
+
readonly type: "console";
|
|
26
|
+
private from;
|
|
27
|
+
private delay;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new ConsoleProvider instance.
|
|
30
|
+
*
|
|
31
|
+
* @param config - The provider configuration
|
|
32
|
+
*/
|
|
33
|
+
constructor(config: SMSProviderConfig & {
|
|
34
|
+
delay?: number;
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Logs an SMS message to the console.
|
|
38
|
+
*
|
|
39
|
+
* @param options - The SMS options
|
|
40
|
+
* @returns A promise that resolves to a successful result
|
|
41
|
+
*/
|
|
42
|
+
send(options: SMSOptions): Promise<SMSResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Logs multiple SMS messages to the console.
|
|
45
|
+
*
|
|
46
|
+
* @param options - The batch SMS options
|
|
47
|
+
* @returns A promise that resolves to the batch result
|
|
48
|
+
*/
|
|
49
|
+
sendBatch(options: BatchSMSOptions): Promise<BatchSMSResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Always returns true for console provider.
|
|
52
|
+
*/
|
|
53
|
+
verify(): Promise<boolean>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a Console provider instance.
|
|
57
|
+
*
|
|
58
|
+
* @param config - The provider configuration
|
|
59
|
+
* @returns A new ConsoleProvider instance
|
|
60
|
+
*/
|
|
61
|
+
declare function createConsoleProvider(config?: SMSProviderConfig & {
|
|
62
|
+
delay?: number;
|
|
63
|
+
}): ConsoleProvider;
|
|
64
|
+
|
|
65
|
+
export { ConsoleProvider, createConsoleProvider };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/providers/console.ts
|
|
2
|
+
var ConsoleProvider = class {
|
|
3
|
+
/** Provider type identifier */
|
|
4
|
+
type = "console";
|
|
5
|
+
from;
|
|
6
|
+
delay;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new ConsoleProvider instance.
|
|
9
|
+
*
|
|
10
|
+
* @param config - The provider configuration
|
|
11
|
+
*/
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.from = config.from || "CONSOLE";
|
|
14
|
+
this.delay = config.delay ?? 100;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Logs an SMS message to the console.
|
|
18
|
+
*
|
|
19
|
+
* @param options - The SMS options
|
|
20
|
+
* @returns A promise that resolves to a successful result
|
|
21
|
+
*/
|
|
22
|
+
async send(options) {
|
|
23
|
+
if (this.delay > 0) {
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, this.delay));
|
|
25
|
+
}
|
|
26
|
+
const from = options.from || this.from;
|
|
27
|
+
const messageId = `console-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
28
|
+
console.log("\n" + "\u2500".repeat(50));
|
|
29
|
+
console.log("\u{1F4F1} SMS (Console Provider)");
|
|
30
|
+
console.log("\u2500".repeat(50));
|
|
31
|
+
console.log(`To: ${options.to}`);
|
|
32
|
+
console.log(`From: ${from}`);
|
|
33
|
+
console.log(`Message: ${options.message}`);
|
|
34
|
+
if (options.tags) {
|
|
35
|
+
console.log(`Tags: ${JSON.stringify(options.tags)}`);
|
|
36
|
+
}
|
|
37
|
+
console.log(`ID: ${messageId}`);
|
|
38
|
+
console.log("\u2500".repeat(50) + "\n");
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
messageId,
|
|
42
|
+
data: { provider: "console", logged: true }
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Logs multiple SMS messages to the console.
|
|
47
|
+
*
|
|
48
|
+
* @param options - The batch SMS options
|
|
49
|
+
* @returns A promise that resolves to the batch result
|
|
50
|
+
*/
|
|
51
|
+
async sendBatch(options) {
|
|
52
|
+
const results = [];
|
|
53
|
+
for (const sms of options.messages) {
|
|
54
|
+
const result = await this.send(sms);
|
|
55
|
+
results.push(result);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
total: options.messages.length,
|
|
59
|
+
successful: options.messages.length,
|
|
60
|
+
failed: 0,
|
|
61
|
+
results
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Always returns true for console provider.
|
|
66
|
+
*/
|
|
67
|
+
async verify() {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function createConsoleProvider(config) {
|
|
72
|
+
return new ConsoleProvider(config || {});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { ConsoleProvider, createConsoleProvider };
|
|
76
|
+
//# sourceMappingURL=console.js.map
|
|
77
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/console.ts"],"names":[],"mappings":"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","file":"console.js","sourcesContent":["/**\n * @parsrun/sms - Console Provider\n * Development provider that logs SMS to console instead of sending\n */\n\nimport type {\n BatchSMSOptions,\n BatchSMSResult,\n SMSOptions,\n SMSProvider,\n SMSProviderConfig,\n SMSResult,\n} from \"../types.js\";\n\n/**\n * Console SMS Provider\n * Logs SMS messages to console for development/testing\n *\n * @example\n * ```typescript\n * const sms = new ConsoleProvider({ from: 'TEST' });\n *\n * await sms.send({\n * to: '905551234567',\n * message: 'Test message',\n * });\n * // Logs: [SMS] To: 905551234567, From: TEST, Message: Test message\n * ```\n */\nexport class ConsoleProvider implements SMSProvider {\n /** Provider type identifier */\n readonly type = \"console\" as const;\n\n private from: string;\n private delay: number;\n\n /**\n * Creates a new ConsoleProvider instance.\n *\n * @param config - The provider configuration\n */\n constructor(config: SMSProviderConfig & { delay?: number }) {\n this.from = config.from || \"CONSOLE\";\n this.delay = config.delay ?? 100; // Simulate network delay\n }\n\n /**\n * Logs an SMS message to the console.\n *\n * @param options - The SMS options\n * @returns A promise that resolves to a successful result\n */\n async send(options: SMSOptions): Promise<SMSResult> {\n // Simulate network delay\n if (this.delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.delay));\n }\n\n const from = options.from || this.from;\n const messageId = `console-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n\n console.log(\"\\n\" + \"─\".repeat(50));\n console.log(\"📱 SMS (Console Provider)\");\n console.log(\"─\".repeat(50));\n console.log(`To: ${options.to}`);\n console.log(`From: ${from}`);\n console.log(`Message: ${options.message}`);\n if (options.tags) {\n console.log(`Tags: ${JSON.stringify(options.tags)}`);\n }\n console.log(`ID: ${messageId}`);\n console.log(\"─\".repeat(50) + \"\\n\");\n\n return {\n success: true,\n messageId,\n data: { provider: \"console\", logged: true },\n };\n }\n\n /**\n * Logs multiple SMS messages to the console.\n *\n * @param options - The batch SMS options\n * @returns A promise that resolves to the batch result\n */\n async sendBatch(options: BatchSMSOptions): Promise<BatchSMSResult> {\n const results: SMSResult[] = [];\n\n for (const sms of options.messages) {\n const result = await this.send(sms);\n results.push(result);\n }\n\n return {\n total: options.messages.length,\n successful: options.messages.length,\n failed: 0,\n results,\n };\n }\n\n /**\n * Always returns true for console provider.\n */\n async verify(): Promise<boolean> {\n return true;\n }\n}\n\n/**\n * Creates a Console provider instance.\n *\n * @param config - The provider configuration\n * @returns A new ConsoleProvider instance\n */\nexport function createConsoleProvider(\n config?: SMSProviderConfig & { delay?: number }\n): ConsoleProvider {\n return new ConsoleProvider(config || {});\n}\n"]}
|