budgetsms-client 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +440 -0
- package/dist/index.cjs +569 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +460 -0
- package/dist/index.d.ts +460 -0
- package/dist/index.js +557 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/constants.ts
|
|
4
|
+
var API_BASE = "https://api.budgetsms.net";
|
|
5
|
+
var ENDPOINTS = {
|
|
6
|
+
SEND_SMS: "/sendsms/",
|
|
7
|
+
TEST_SMS: "/testsms/",
|
|
8
|
+
CHECK_CREDIT: "/checkcredit/",
|
|
9
|
+
CHECK_OPERATOR: "/checkoperator/",
|
|
10
|
+
HLR: "/hlr/",
|
|
11
|
+
CHECK_SMS: "/checksms/",
|
|
12
|
+
GET_PRICING: "/getpricing/"
|
|
13
|
+
};
|
|
14
|
+
var BudgetSMSErrorCode = /* @__PURE__ */ ((BudgetSMSErrorCode2) => {
|
|
15
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NOT_ENOUGH_CREDITS"] = 1001] = "NOT_ENOUGH_CREDITS";
|
|
16
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["INVALID_CREDENTIALS"] = 1002] = "INVALID_CREDENTIALS";
|
|
17
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["ACCOUNT_NOT_ACTIVE"] = 1003] = "ACCOUNT_NOT_ACTIVE";
|
|
18
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["IP_NOT_ALLOWED"] = 1004] = "IP_NOT_ALLOWED";
|
|
19
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_HANDLE_PROVIDED"] = 1005] = "NO_HANDLE_PROVIDED";
|
|
20
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_USERID_PROVIDED"] = 1006] = "NO_USERID_PROVIDED";
|
|
21
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_USERNAME_PROVIDED"] = 1007] = "NO_USERNAME_PROVIDED";
|
|
22
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_TEXT_EMPTY"] = 2001] = "SMS_TEXT_EMPTY";
|
|
23
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_NUMERIC_SENDER_TOO_LONG"] = 2002] = "SMS_NUMERIC_SENDER_TOO_LONG";
|
|
24
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_ALPHANUMERIC_SENDER_TOO_LONG"] = 2003] = "SMS_ALPHANUMERIC_SENDER_TOO_LONG";
|
|
25
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_SENDER_EMPTY_OR_INVALID"] = 2004] = "SMS_SENDER_EMPTY_OR_INVALID";
|
|
26
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["DESTINATION_TOO_SHORT"] = 2005] = "DESTINATION_TOO_SHORT";
|
|
27
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["DESTINATION_NOT_NUMERIC"] = 2006] = "DESTINATION_NOT_NUMERIC";
|
|
28
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["DESTINATION_EMPTY"] = 2007] = "DESTINATION_EMPTY";
|
|
29
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_TEXT_NOT_OK"] = 2008] = "SMS_TEXT_NOT_OK";
|
|
30
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["PARAMETER_ISSUE"] = 2009] = "PARAMETER_ISSUE";
|
|
31
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["DESTINATION_INVALIDLY_FORMATTED"] = 2010] = "DESTINATION_INVALIDLY_FORMATTED";
|
|
32
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["DESTINATION_INVALID"] = 2011] = "DESTINATION_INVALID";
|
|
33
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_TEXT_TOO_LONG"] = 2012] = "SMS_TEXT_TOO_LONG";
|
|
34
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SMS_MESSAGE_INVALID"] = 2013] = "SMS_MESSAGE_INVALID";
|
|
35
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["CUSTOM_ID_ALREADY_USED"] = 2014] = "CUSTOM_ID_ALREADY_USED";
|
|
36
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["CHARSET_PROBLEM"] = 2015] = "CHARSET_PROBLEM";
|
|
37
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["INVALID_UTF8_ENCODING"] = 2016] = "INVALID_UTF8_ENCODING";
|
|
38
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["INVALID_SMS_ID"] = 2017] = "INVALID_SMS_ID";
|
|
39
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_ROUTE_TO_DESTINATION"] = 3001] = "NO_ROUTE_TO_DESTINATION";
|
|
40
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_ROUTES_SETUP"] = 3002] = "NO_ROUTES_SETUP";
|
|
41
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["INVALID_DESTINATION"] = 3003] = "INVALID_DESTINATION";
|
|
42
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_CUSTOM_ID"] = 4001] = "SYSTEM_ERROR_CUSTOM_ID";
|
|
43
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_TEMPORARY"] = 4002] = "SYSTEM_ERROR_TEMPORARY";
|
|
44
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_TEMPORARY_2"] = 4003] = "SYSTEM_ERROR_TEMPORARY_2";
|
|
45
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_CONTACT_SUPPORT"] = 4004] = "SYSTEM_ERROR_CONTACT_SUPPORT";
|
|
46
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_PERMANENT"] = 4005] = "SYSTEM_ERROR_PERMANENT";
|
|
47
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["GATEWAY_NOT_REACHABLE"] = 4006] = "GATEWAY_NOT_REACHABLE";
|
|
48
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SYSTEM_ERROR_CONTACT_SUPPORT_2"] = 4007] = "SYSTEM_ERROR_CONTACT_SUPPORT_2";
|
|
49
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["SEND_ERROR"] = 5001] = "SEND_ERROR";
|
|
50
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["WRONG_SMS_TYPE"] = 5002] = "WRONG_SMS_TYPE";
|
|
51
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["WRONG_OPERATOR"] = 5003] = "WRONG_OPERATOR";
|
|
52
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["UNKNOWN_ERROR"] = 6001] = "UNKNOWN_ERROR";
|
|
53
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["NO_HLR_PROVIDER"] = 7001] = "NO_HLR_PROVIDER";
|
|
54
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["UNEXPECTED_HLR_RESULTS"] = 7002] = "UNEXPECTED_HLR_RESULTS";
|
|
55
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["BAD_NUMBER_FORMAT"] = 7003] = "BAD_NUMBER_FORMAT";
|
|
56
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["HLR_UNEXPECTED_ERROR"] = 7901] = "HLR_UNEXPECTED_ERROR";
|
|
57
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["HLR_PROVIDER_ERROR"] = 7902] = "HLR_PROVIDER_ERROR";
|
|
58
|
+
BudgetSMSErrorCode2[BudgetSMSErrorCode2["HLR_PROVIDER_ERROR_2"] = 7903] = "HLR_PROVIDER_ERROR_2";
|
|
59
|
+
return BudgetSMSErrorCode2;
|
|
60
|
+
})(BudgetSMSErrorCode || {});
|
|
61
|
+
var ERROR_MESSAGES = {
|
|
62
|
+
[1001 /* NOT_ENOUGH_CREDITS */]: "Not enough credits to send messages",
|
|
63
|
+
[1002 /* INVALID_CREDENTIALS */]: "Identification failed. Wrong credentials",
|
|
64
|
+
[1003 /* ACCOUNT_NOT_ACTIVE */]: "Account not active, contact BudgetSMS",
|
|
65
|
+
[1004 /* IP_NOT_ALLOWED */]: "This IP address is not added to this account. No access to the API",
|
|
66
|
+
[1005 /* NO_HANDLE_PROVIDED */]: "No handle provided",
|
|
67
|
+
[1006 /* NO_USERID_PROVIDED */]: "No UserID provided",
|
|
68
|
+
[1007 /* NO_USERNAME_PROVIDED */]: "No Username provided",
|
|
69
|
+
[2001 /* SMS_TEXT_EMPTY */]: "SMS message text is empty",
|
|
70
|
+
[2002 /* SMS_NUMERIC_SENDER_TOO_LONG */]: "SMS numeric senderid can be max. 16 numbers",
|
|
71
|
+
[2003 /* SMS_ALPHANUMERIC_SENDER_TOO_LONG */]: "SMS alphanumeric sender can be max. 11 characters",
|
|
72
|
+
[2004 /* SMS_SENDER_EMPTY_OR_INVALID */]: "SMS senderid is empty or invalid",
|
|
73
|
+
[2005 /* DESTINATION_TOO_SHORT */]: "Destination number is too short",
|
|
74
|
+
[2006 /* DESTINATION_NOT_NUMERIC */]: "Destination is not numeric",
|
|
75
|
+
[2007 /* DESTINATION_EMPTY */]: "Destination is empty",
|
|
76
|
+
[2008 /* SMS_TEXT_NOT_OK */]: "SMS text is not OK (check encoding?)",
|
|
77
|
+
[2009 /* PARAMETER_ISSUE */]: "Parameter issue (check all mandatory parameters, encoding, etc.)",
|
|
78
|
+
[2010 /* DESTINATION_INVALIDLY_FORMATTED */]: "Destination number is invalidly formatted",
|
|
79
|
+
[2011 /* DESTINATION_INVALID */]: "Destination is invalid",
|
|
80
|
+
[2012 /* SMS_TEXT_TOO_LONG */]: "SMS message text is too long",
|
|
81
|
+
[2013 /* SMS_MESSAGE_INVALID */]: "SMS message is invalid",
|
|
82
|
+
[2014 /* CUSTOM_ID_ALREADY_USED */]: "SMS CustomID is used before",
|
|
83
|
+
[2015 /* CHARSET_PROBLEM */]: "Charset problem",
|
|
84
|
+
[2016 /* INVALID_UTF8_ENCODING */]: "Invalid UTF-8 encoding",
|
|
85
|
+
[2017 /* INVALID_SMS_ID */]: "Invalid SMSid",
|
|
86
|
+
[3001 /* NO_ROUTE_TO_DESTINATION */]: "No route to destination. Contact BudgetSMS for possible solutions",
|
|
87
|
+
[3002 /* NO_ROUTES_SETUP */]: "No routes are setup. Contact BudgetSMS for a route setup",
|
|
88
|
+
[3003 /* INVALID_DESTINATION */]: "Invalid destination. Check international mobile number formatting",
|
|
89
|
+
[4001 /* SYSTEM_ERROR_CUSTOM_ID */]: "System error, related to customID",
|
|
90
|
+
[4002 /* SYSTEM_ERROR_TEMPORARY */]: "System error, temporary issue. Try resubmitting in 2 to 3 minutes",
|
|
91
|
+
[4003 /* SYSTEM_ERROR_TEMPORARY_2 */]: "System error, temporary issue",
|
|
92
|
+
[4004 /* SYSTEM_ERROR_CONTACT_SUPPORT */]: "System error, temporary issue. Contact BudgetSMS",
|
|
93
|
+
[4005 /* SYSTEM_ERROR_PERMANENT */]: "System error, permanent",
|
|
94
|
+
[4006 /* GATEWAY_NOT_REACHABLE */]: "Gateway not reachable",
|
|
95
|
+
[4007 /* SYSTEM_ERROR_CONTACT_SUPPORT_2 */]: "System error, contact BudgetSMS",
|
|
96
|
+
[5001 /* SEND_ERROR */]: "Send error, Contact BudgetSMS with the send details",
|
|
97
|
+
[5002 /* WRONG_SMS_TYPE */]: "Wrong SMS type",
|
|
98
|
+
[5003 /* WRONG_OPERATOR */]: "Wrong operator",
|
|
99
|
+
[6001 /* UNKNOWN_ERROR */]: "Unknown error",
|
|
100
|
+
[7001 /* NO_HLR_PROVIDER */]: "No HLR provider present, Contact BudgetSMS",
|
|
101
|
+
[7002 /* UNEXPECTED_HLR_RESULTS */]: "Unexpected results from HLR provider",
|
|
102
|
+
[7003 /* BAD_NUMBER_FORMAT */]: "Bad number format",
|
|
103
|
+
[7901 /* HLR_UNEXPECTED_ERROR */]: "Unexpected error. Contact BudgetSMS",
|
|
104
|
+
[7902 /* HLR_PROVIDER_ERROR */]: "HLR provider error. Contact BudgetSMS",
|
|
105
|
+
[7903 /* HLR_PROVIDER_ERROR_2 */]: "HLR provider error. Contact BudgetSMS"
|
|
106
|
+
};
|
|
107
|
+
var DLRStatus = /* @__PURE__ */ ((DLRStatus2) => {
|
|
108
|
+
DLRStatus2[DLRStatus2["SENT_NO_STATUS"] = 0] = "SENT_NO_STATUS";
|
|
109
|
+
DLRStatus2[DLRStatus2["DELIVERED"] = 1] = "DELIVERED";
|
|
110
|
+
DLRStatus2[DLRStatus2["NOT_SENT"] = 2] = "NOT_SENT";
|
|
111
|
+
DLRStatus2[DLRStatus2["DELIVERY_FAILED"] = 3] = "DELIVERY_FAILED";
|
|
112
|
+
DLRStatus2[DLRStatus2["SENT"] = 4] = "SENT";
|
|
113
|
+
DLRStatus2[DLRStatus2["EXPIRED"] = 5] = "EXPIRED";
|
|
114
|
+
DLRStatus2[DLRStatus2["INVALID_DESTINATION"] = 6] = "INVALID_DESTINATION";
|
|
115
|
+
DLRStatus2[DLRStatus2["SMSC_ERROR"] = 7] = "SMSC_ERROR";
|
|
116
|
+
DLRStatus2[DLRStatus2["NOT_ALLOWED"] = 8] = "NOT_ALLOWED";
|
|
117
|
+
DLRStatus2[DLRStatus2["STATUS_UNKNOWN_24H"] = 11] = "STATUS_UNKNOWN_24H";
|
|
118
|
+
DLRStatus2[DLRStatus2["STATUS_UNKNOWN_CODE"] = 12] = "STATUS_UNKNOWN_CODE";
|
|
119
|
+
DLRStatus2[DLRStatus2["STATUS_UNKNOWN_72H"] = 13] = "STATUS_UNKNOWN_72H";
|
|
120
|
+
return DLRStatus2;
|
|
121
|
+
})(DLRStatus || {});
|
|
122
|
+
var DLR_STATUS_MESSAGES = {
|
|
123
|
+
[0 /* SENT_NO_STATUS */]: "Message is sent, no status yet",
|
|
124
|
+
[1 /* DELIVERED */]: "Message is delivered",
|
|
125
|
+
[2 /* NOT_SENT */]: "Message is not sent",
|
|
126
|
+
[3 /* DELIVERY_FAILED */]: "Message delivery failed",
|
|
127
|
+
[4 /* SENT */]: "Message is sent",
|
|
128
|
+
[5 /* EXPIRED */]: "Message expired",
|
|
129
|
+
[6 /* INVALID_DESTINATION */]: "Message has invalid destination address",
|
|
130
|
+
[7 /* SMSC_ERROR */]: "SMSC error, message could not be processed",
|
|
131
|
+
[8 /* NOT_ALLOWED */]: "Message is not allowed",
|
|
132
|
+
[11 /* STATUS_UNKNOWN_24H */]: "Message status unknown, usually after 24 hours without status update from SMSC",
|
|
133
|
+
[12 /* STATUS_UNKNOWN_CODE */]: "Message status unknown, SMSC received unknown status code",
|
|
134
|
+
[13 /* STATUS_UNKNOWN_72H */]: "Message status unknown, no status update received from SMSC after 72 hours"
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/errors.ts
|
|
138
|
+
var BudgetSMSError = class _BudgetSMSError extends Error {
|
|
139
|
+
/**
|
|
140
|
+
* Creates a new BudgetSMSError
|
|
141
|
+
* @param code - The BudgetSMS error code
|
|
142
|
+
* @param message - Optional custom error message (defaults to standard message for the code)
|
|
143
|
+
*/
|
|
144
|
+
constructor(code, message) {
|
|
145
|
+
super(message || ERROR_MESSAGES[code] || `BudgetSMS API error: ${code}`);
|
|
146
|
+
this.code = code;
|
|
147
|
+
this.name = "BudgetSMSError";
|
|
148
|
+
if (Error.captureStackTrace) {
|
|
149
|
+
Error.captureStackTrace(this, _BudgetSMSError);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Returns true if the error code indicates a temporary/retryable error
|
|
154
|
+
*/
|
|
155
|
+
isRetryable() {
|
|
156
|
+
return [
|
|
157
|
+
4002 /* SYSTEM_ERROR_TEMPORARY */,
|
|
158
|
+
4003 /* SYSTEM_ERROR_TEMPORARY_2 */,
|
|
159
|
+
4006 /* GATEWAY_NOT_REACHABLE */
|
|
160
|
+
].includes(this.code);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Returns true if the error code indicates an authentication/credentials issue
|
|
164
|
+
*/
|
|
165
|
+
isAuthenticationError() {
|
|
166
|
+
return [
|
|
167
|
+
1002 /* INVALID_CREDENTIALS */,
|
|
168
|
+
1003 /* ACCOUNT_NOT_ACTIVE */,
|
|
169
|
+
1004 /* IP_NOT_ALLOWED */,
|
|
170
|
+
1005 /* NO_HANDLE_PROVIDED */,
|
|
171
|
+
1006 /* NO_USERID_PROVIDED */,
|
|
172
|
+
1007 /* NO_USERNAME_PROVIDED */
|
|
173
|
+
].includes(this.code);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns true if the error code indicates insufficient credits
|
|
177
|
+
*/
|
|
178
|
+
isInsufficientCredits() {
|
|
179
|
+
return this.code === 1001 /* NOT_ENOUGH_CREDITS */;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Convert error to JSON for logging/serialization
|
|
183
|
+
*/
|
|
184
|
+
toJSON() {
|
|
185
|
+
return {
|
|
186
|
+
name: this.name,
|
|
187
|
+
code: this.code,
|
|
188
|
+
message: this.message,
|
|
189
|
+
stack: this.stack
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/utils.ts
|
|
195
|
+
function buildQueryString(params) {
|
|
196
|
+
const pairs = [];
|
|
197
|
+
for (const [key, value] of Object.entries(params)) {
|
|
198
|
+
if (value !== void 0 && value !== null) {
|
|
199
|
+
const stringValue = typeof value === "boolean" ? value ? "1" : "0" : String(value);
|
|
200
|
+
pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(stringValue)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return pairs.join("&");
|
|
204
|
+
}
|
|
205
|
+
function parseResponse(response) {
|
|
206
|
+
const trimmed = response.trim();
|
|
207
|
+
if (trimmed.startsWith("ERR ")) {
|
|
208
|
+
const errorCode = parseInt(trimmed.substring(4), 10);
|
|
209
|
+
if (isNaN(errorCode)) {
|
|
210
|
+
throw new Error(`Invalid error response format: ${trimmed}`);
|
|
211
|
+
}
|
|
212
|
+
throw new BudgetSMSError(errorCode);
|
|
213
|
+
}
|
|
214
|
+
if (trimmed.startsWith("OK ")) {
|
|
215
|
+
return trimmed.substring(3).trim();
|
|
216
|
+
}
|
|
217
|
+
if (trimmed === "OK") {
|
|
218
|
+
return "";
|
|
219
|
+
}
|
|
220
|
+
throw new Error(`Unexpected API response format: ${trimmed}`);
|
|
221
|
+
}
|
|
222
|
+
function parseSendSMSResponse(response, includePrice, includeMccMnc, includeCredit) {
|
|
223
|
+
const data = parseResponse(response);
|
|
224
|
+
const parts = data.split(/\s+/);
|
|
225
|
+
if (parts.length === 0) {
|
|
226
|
+
throw new Error("Invalid send SMS response: no SMS ID found");
|
|
227
|
+
}
|
|
228
|
+
const result = {
|
|
229
|
+
success: true,
|
|
230
|
+
smsId: parts[0]
|
|
231
|
+
};
|
|
232
|
+
let index = 1;
|
|
233
|
+
if (includePrice && parts.length > index + 1) {
|
|
234
|
+
result.price = parseFloat(parts[index]);
|
|
235
|
+
result.parts = parseInt(parts[index + 1], 10);
|
|
236
|
+
index += 2;
|
|
237
|
+
}
|
|
238
|
+
if (includeMccMnc && parts.length > index) {
|
|
239
|
+
result.mccMnc = parts[index];
|
|
240
|
+
index += 1;
|
|
241
|
+
}
|
|
242
|
+
if (includeCredit && parts.length > index) {
|
|
243
|
+
result.credit = parseFloat(parts[index]);
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
function parseCheckCreditResponse(response) {
|
|
248
|
+
const data = parseResponse(response);
|
|
249
|
+
const credit = parseFloat(data);
|
|
250
|
+
if (isNaN(credit)) {
|
|
251
|
+
throw new Error(`Invalid credit response: ${data}`);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
success: true,
|
|
255
|
+
credit
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function parseOperatorResponse(response) {
|
|
259
|
+
const data = parseResponse(response);
|
|
260
|
+
const parts = data.split(":");
|
|
261
|
+
if (parts.length < 3) {
|
|
262
|
+
throw new Error(`Invalid operator response format: ${data}`);
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
success: true,
|
|
266
|
+
mccMnc: parts[0],
|
|
267
|
+
operatorName: parts[1],
|
|
268
|
+
messageCost: parseFloat(parts[2])
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function parseSMSStatusResponse(response, smsId) {
|
|
272
|
+
const data = parseResponse(response);
|
|
273
|
+
const status = parseInt(data, 10);
|
|
274
|
+
if (isNaN(status)) {
|
|
275
|
+
throw new Error(`Invalid status response: ${data}`);
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
success: true,
|
|
279
|
+
smsId,
|
|
280
|
+
status
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function parsePricingResponse(response) {
|
|
284
|
+
if (response.trim().startsWith("ERR ")) {
|
|
285
|
+
parseResponse(response);
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
const pricing = JSON.parse(response);
|
|
289
|
+
if (!Array.isArray(pricing)) {
|
|
290
|
+
throw new Error("Pricing response is not an array");
|
|
291
|
+
}
|
|
292
|
+
return pricing;
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (error instanceof BudgetSMSError) {
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`Failed to parse pricing response: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function validatePhoneNumber(phoneNumber) {
|
|
301
|
+
return /^\d{8,16}$/.test(phoneNumber);
|
|
302
|
+
}
|
|
303
|
+
function validateSender(sender) {
|
|
304
|
+
if (/^[a-zA-Z0-9]{1,11}$/.test(sender)) {
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
if (/^\d{1,16}$/.test(sender)) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
function validateMessage(message) {
|
|
313
|
+
return message.length > 0 && message.length <= 612;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/client.ts
|
|
317
|
+
var BudgetSMS = class {
|
|
318
|
+
username;
|
|
319
|
+
userid;
|
|
320
|
+
handle;
|
|
321
|
+
baseUrl;
|
|
322
|
+
timeout;
|
|
323
|
+
/**
|
|
324
|
+
* Create a new BudgetSMS client
|
|
325
|
+
* @param config - Configuration object with credentials and optional settings
|
|
326
|
+
*/
|
|
327
|
+
constructor(config) {
|
|
328
|
+
this.username = config.username;
|
|
329
|
+
this.userid = config.userid;
|
|
330
|
+
this.handle = config.handle;
|
|
331
|
+
this.baseUrl = config.baseUrl || API_BASE;
|
|
332
|
+
this.timeout = config.timeout || 3e4;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Make an HTTP GET request to the API
|
|
336
|
+
* @param endpoint - API endpoint path
|
|
337
|
+
* @param params - Query parameters
|
|
338
|
+
* @returns Response text
|
|
339
|
+
*/
|
|
340
|
+
async request(endpoint, params = {}) {
|
|
341
|
+
const queryString = buildQueryString(params);
|
|
342
|
+
const url = `${this.baseUrl}${endpoint}?${queryString}`;
|
|
343
|
+
const controller = new AbortController();
|
|
344
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
345
|
+
try {
|
|
346
|
+
const response = await fetch(url, {
|
|
347
|
+
method: "GET",
|
|
348
|
+
signal: controller.signal
|
|
349
|
+
});
|
|
350
|
+
if (!response.ok) {
|
|
351
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
352
|
+
}
|
|
353
|
+
return await response.text();
|
|
354
|
+
} catch (error) {
|
|
355
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
356
|
+
throw new Error(`Request timeout after ${this.timeout}ms`);
|
|
357
|
+
}
|
|
358
|
+
throw error;
|
|
359
|
+
} finally {
|
|
360
|
+
clearTimeout(timeoutId);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Get base authentication parameters
|
|
365
|
+
*/
|
|
366
|
+
getAuthParams() {
|
|
367
|
+
return {
|
|
368
|
+
username: this.username,
|
|
369
|
+
userid: this.userid,
|
|
370
|
+
handle: this.handle
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Send an SMS message
|
|
375
|
+
*
|
|
376
|
+
* @param params - SMS parameters
|
|
377
|
+
* @returns Promise resolving to SendSMSResponse
|
|
378
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```typescript
|
|
382
|
+
* const result = await client.sendSMS({
|
|
383
|
+
* msg: 'Hello World!',
|
|
384
|
+
* from: 'YourApp',
|
|
385
|
+
* to: '31612345678',
|
|
386
|
+
* price: true, // Get price info in response
|
|
387
|
+
* mccmnc: true // Get operator info in response
|
|
388
|
+
* });
|
|
389
|
+
*
|
|
390
|
+
* console.log(`SMS sent with ID: ${result.smsId}`);
|
|
391
|
+
* if (result.price) {
|
|
392
|
+
* console.log(`Cost: €${result.price} for ${result.parts} part(s)`);
|
|
393
|
+
* }
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
async sendSMS(params) {
|
|
397
|
+
const requestParams = {
|
|
398
|
+
...this.getAuthParams(),
|
|
399
|
+
msg: params.msg,
|
|
400
|
+
from: params.from,
|
|
401
|
+
to: params.to,
|
|
402
|
+
customid: params.customid,
|
|
403
|
+
price: params.price,
|
|
404
|
+
mccmnc: params.mccmnc,
|
|
405
|
+
credit: params.credit
|
|
406
|
+
};
|
|
407
|
+
const response = await this.request(ENDPOINTS.SEND_SMS, requestParams);
|
|
408
|
+
return parseSendSMSResponse(response, params.price, params.mccmnc, params.credit);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Test SMS sending without actually sending or reducing credit
|
|
412
|
+
*
|
|
413
|
+
* Useful for testing your implementation without consuming credits.
|
|
414
|
+
*
|
|
415
|
+
* @param params - SMS parameters (same as sendSMS)
|
|
416
|
+
* @returns Promise resolving to TestSMSResponse
|
|
417
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```typescript
|
|
421
|
+
* const result = await client.testSMS({
|
|
422
|
+
* msg: 'Test message',
|
|
423
|
+
* from: 'TestApp',
|
|
424
|
+
* to: '31612345678'
|
|
425
|
+
* });
|
|
426
|
+
*
|
|
427
|
+
* console.log(`Test successful, would get SMS ID: ${result.smsId}`);
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
async testSMS(params) {
|
|
431
|
+
const requestParams = {
|
|
432
|
+
...this.getAuthParams(),
|
|
433
|
+
msg: params.msg,
|
|
434
|
+
from: params.from,
|
|
435
|
+
to: params.to,
|
|
436
|
+
customid: params.customid,
|
|
437
|
+
price: params.price,
|
|
438
|
+
mccmnc: params.mccmnc,
|
|
439
|
+
credit: params.credit
|
|
440
|
+
};
|
|
441
|
+
const response = await this.request(ENDPOINTS.TEST_SMS, requestParams);
|
|
442
|
+
return parseSendSMSResponse(response, params.price, params.mccmnc, params.credit);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Check remaining account credit
|
|
446
|
+
*
|
|
447
|
+
* @returns Promise resolving to CheckCreditResponse
|
|
448
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```typescript
|
|
452
|
+
* const result = await client.checkCredit();
|
|
453
|
+
* console.log(`Remaining credit: €${result.credit}`);
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
456
|
+
async checkCredit() {
|
|
457
|
+
const response = await this.request(ENDPOINTS.CHECK_CREDIT, this.getAuthParams());
|
|
458
|
+
return parseCheckCreditResponse(response);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Check operator based on phone number prefix
|
|
462
|
+
*
|
|
463
|
+
* Note: This checks the original operator based on prefix.
|
|
464
|
+
* If a number has been ported, use hlr() instead.
|
|
465
|
+
*
|
|
466
|
+
* @param phoneNumber - Phone number to check (international format, no +)
|
|
467
|
+
* @returns Promise resolving to OperatorResponse
|
|
468
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```typescript
|
|
472
|
+
* const result = await client.checkOperator('31612345678');
|
|
473
|
+
* console.log(`Operator: ${result.operatorName} (${result.mccMnc})`);
|
|
474
|
+
* console.log(`Cost: €${result.messageCost}`);
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
async checkOperator(phoneNumber) {
|
|
478
|
+
const requestParams = {
|
|
479
|
+
...this.getAuthParams(),
|
|
480
|
+
check: phoneNumber
|
|
481
|
+
};
|
|
482
|
+
const response = await this.request(ENDPOINTS.CHECK_OPERATOR, requestParams);
|
|
483
|
+
return parseOperatorResponse(response);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Perform HLR (Home Location Register) lookup
|
|
487
|
+
*
|
|
488
|
+
* Returns the actual current operator, even if the number has been ported.
|
|
489
|
+
* More accurate than checkOperator() but may cost credits.
|
|
490
|
+
*
|
|
491
|
+
* @param phoneNumber - Phone number to lookup (international format, no +)
|
|
492
|
+
* @returns Promise resolving to HLRResponse
|
|
493
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* ```typescript
|
|
497
|
+
* const result = await client.hlr('31612345678');
|
|
498
|
+
* console.log(`Current operator: ${result.operatorName}`);
|
|
499
|
+
* console.log(`Network: ${result.mccMnc}`);
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
async hlr(phoneNumber) {
|
|
503
|
+
const requestParams = {
|
|
504
|
+
...this.getAuthParams(),
|
|
505
|
+
to: phoneNumber
|
|
506
|
+
};
|
|
507
|
+
const response = await this.request(ENDPOINTS.HLR, requestParams);
|
|
508
|
+
return parseOperatorResponse(response);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Check SMS delivery status (Pull DLR)
|
|
512
|
+
*
|
|
513
|
+
* Retrieve the current delivery status of a sent message.
|
|
514
|
+
* For automatic updates, consider using Push DLR instead.
|
|
515
|
+
*
|
|
516
|
+
* @param smsId - The SMS ID returned from sendSMS()
|
|
517
|
+
* @returns Promise resolving to SMSStatusResponse
|
|
518
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```typescript
|
|
522
|
+
* const result = await client.checkSMS('12345678');
|
|
523
|
+
* console.log(`Status: ${result.status}`); // DLRStatus enum value
|
|
524
|
+
* ```
|
|
525
|
+
*/
|
|
526
|
+
async checkSMS(smsId) {
|
|
527
|
+
const requestParams = {
|
|
528
|
+
...this.getAuthParams(),
|
|
529
|
+
smsid: smsId
|
|
530
|
+
};
|
|
531
|
+
const response = await this.request(ENDPOINTS.CHECK_SMS, requestParams);
|
|
532
|
+
return parseSMSStatusResponse(response, smsId);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Get account pricing for all operators
|
|
536
|
+
*
|
|
537
|
+
* Returns a comprehensive list of pricing for all available operators.
|
|
538
|
+
* Each entry includes country, operator, MCC/MNC codes, and pricing info.
|
|
539
|
+
*
|
|
540
|
+
* @returns Promise resolving to GetPricingResponse (array of pricing entries)
|
|
541
|
+
* @throws {BudgetSMSError} If the API returns an error
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* const pricing = await client.getPricing();
|
|
546
|
+
* for (const entry of pricing) {
|
|
547
|
+
* console.log(`${entry.countryname} - ${entry.operatorname}: €${entry.price}`);
|
|
548
|
+
* }
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
async getPricing() {
|
|
552
|
+
const response = await this.request(ENDPOINTS.GET_PRICING, this.getAuthParams());
|
|
553
|
+
return parsePricingResponse(response);
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
exports.API_BASE = API_BASE;
|
|
558
|
+
exports.BudgetSMS = BudgetSMS;
|
|
559
|
+
exports.BudgetSMSError = BudgetSMSError;
|
|
560
|
+
exports.BudgetSMSErrorCode = BudgetSMSErrorCode;
|
|
561
|
+
exports.DLRStatus = DLRStatus;
|
|
562
|
+
exports.DLR_STATUS_MESSAGES = DLR_STATUS_MESSAGES;
|
|
563
|
+
exports.ENDPOINTS = ENDPOINTS;
|
|
564
|
+
exports.ERROR_MESSAGES = ERROR_MESSAGES;
|
|
565
|
+
exports.validateMessage = validateMessage;
|
|
566
|
+
exports.validatePhoneNumber = validatePhoneNumber;
|
|
567
|
+
exports.validateSender = validateSender;
|
|
568
|
+
//# sourceMappingURL=index.cjs.map
|
|
569
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/utils.ts","../src/client.ts"],"names":["BudgetSMSErrorCode","DLRStatus"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * BudgetSMS API Base URL and Endpoints\n */\nexport const API_BASE = 'https://api.budgetsms.net';\n\nexport const ENDPOINTS = {\n SEND_SMS: '/sendsms/',\n TEST_SMS: '/testsms/',\n CHECK_CREDIT: '/checkcredit/',\n CHECK_OPERATOR: '/checkoperator/',\n HLR: '/hlr/',\n CHECK_SMS: '/checksms/',\n GET_PRICING: '/getpricing/',\n} as const;\n\n/**\n * BudgetSMS API Error Codes\n * Source: HTTP API Specification V2.7, Chapter 11\n */\nexport enum BudgetSMSErrorCode {\n // Authentication & Account Errors (1xxx)\n NOT_ENOUGH_CREDITS = 1001,\n INVALID_CREDENTIALS = 1002,\n ACCOUNT_NOT_ACTIVE = 1003,\n IP_NOT_ALLOWED = 1004,\n NO_HANDLE_PROVIDED = 1005,\n NO_USERID_PROVIDED = 1006,\n NO_USERNAME_PROVIDED = 1007,\n\n // SMS Message Errors (2xxx)\n SMS_TEXT_EMPTY = 2001,\n SMS_NUMERIC_SENDER_TOO_LONG = 2002,\n SMS_ALPHANUMERIC_SENDER_TOO_LONG = 2003,\n SMS_SENDER_EMPTY_OR_INVALID = 2004,\n DESTINATION_TOO_SHORT = 2005,\n DESTINATION_NOT_NUMERIC = 2006,\n DESTINATION_EMPTY = 2007,\n SMS_TEXT_NOT_OK = 2008,\n PARAMETER_ISSUE = 2009,\n DESTINATION_INVALIDLY_FORMATTED = 2010,\n DESTINATION_INVALID = 2011,\n SMS_TEXT_TOO_LONG = 2012,\n SMS_MESSAGE_INVALID = 2013,\n CUSTOM_ID_ALREADY_USED = 2014,\n CHARSET_PROBLEM = 2015,\n INVALID_UTF8_ENCODING = 2016,\n INVALID_SMS_ID = 2017,\n\n // Routing Errors (3xxx)\n NO_ROUTE_TO_DESTINATION = 3001,\n NO_ROUTES_SETUP = 3002,\n INVALID_DESTINATION = 3003,\n\n // System Errors (4xxx)\n SYSTEM_ERROR_CUSTOM_ID = 4001,\n SYSTEM_ERROR_TEMPORARY = 4002,\n SYSTEM_ERROR_TEMPORARY_2 = 4003,\n SYSTEM_ERROR_CONTACT_SUPPORT = 4004,\n SYSTEM_ERROR_PERMANENT = 4005,\n GATEWAY_NOT_REACHABLE = 4006,\n SYSTEM_ERROR_CONTACT_SUPPORT_2 = 4007,\n\n // Send Errors (5xxx)\n SEND_ERROR = 5001,\n WRONG_SMS_TYPE = 5002,\n WRONG_OPERATOR = 5003,\n\n // Unknown Error (6xxx)\n UNKNOWN_ERROR = 6001,\n\n // HLR Errors (7xxx)\n NO_HLR_PROVIDER = 7001,\n UNEXPECTED_HLR_RESULTS = 7002,\n BAD_NUMBER_FORMAT = 7003,\n HLR_UNEXPECTED_ERROR = 7901,\n HLR_PROVIDER_ERROR = 7902,\n HLR_PROVIDER_ERROR_2 = 7903,\n}\n\n/**\n * Error code descriptions for better error messages\n */\nexport const ERROR_MESSAGES: Record<BudgetSMSErrorCode, string> = {\n [BudgetSMSErrorCode.NOT_ENOUGH_CREDITS]: 'Not enough credits to send messages',\n [BudgetSMSErrorCode.INVALID_CREDENTIALS]: 'Identification failed. Wrong credentials',\n [BudgetSMSErrorCode.ACCOUNT_NOT_ACTIVE]: 'Account not active, contact BudgetSMS',\n [BudgetSMSErrorCode.IP_NOT_ALLOWED]: 'This IP address is not added to this account. No access to the API',\n [BudgetSMSErrorCode.NO_HANDLE_PROVIDED]: 'No handle provided',\n [BudgetSMSErrorCode.NO_USERID_PROVIDED]: 'No UserID provided',\n [BudgetSMSErrorCode.NO_USERNAME_PROVIDED]: 'No Username provided',\n\n [BudgetSMSErrorCode.SMS_TEXT_EMPTY]: 'SMS message text is empty',\n [BudgetSMSErrorCode.SMS_NUMERIC_SENDER_TOO_LONG]: 'SMS numeric senderid can be max. 16 numbers',\n [BudgetSMSErrorCode.SMS_ALPHANUMERIC_SENDER_TOO_LONG]: 'SMS alphanumeric sender can be max. 11 characters',\n [BudgetSMSErrorCode.SMS_SENDER_EMPTY_OR_INVALID]: 'SMS senderid is empty or invalid',\n [BudgetSMSErrorCode.DESTINATION_TOO_SHORT]: 'Destination number is too short',\n [BudgetSMSErrorCode.DESTINATION_NOT_NUMERIC]: 'Destination is not numeric',\n [BudgetSMSErrorCode.DESTINATION_EMPTY]: 'Destination is empty',\n [BudgetSMSErrorCode.SMS_TEXT_NOT_OK]: 'SMS text is not OK (check encoding?)',\n [BudgetSMSErrorCode.PARAMETER_ISSUE]: 'Parameter issue (check all mandatory parameters, encoding, etc.)',\n [BudgetSMSErrorCode.DESTINATION_INVALIDLY_FORMATTED]: 'Destination number is invalidly formatted',\n [BudgetSMSErrorCode.DESTINATION_INVALID]: 'Destination is invalid',\n [BudgetSMSErrorCode.SMS_TEXT_TOO_LONG]: 'SMS message text is too long',\n [BudgetSMSErrorCode.SMS_MESSAGE_INVALID]: 'SMS message is invalid',\n [BudgetSMSErrorCode.CUSTOM_ID_ALREADY_USED]: 'SMS CustomID is used before',\n [BudgetSMSErrorCode.CHARSET_PROBLEM]: 'Charset problem',\n [BudgetSMSErrorCode.INVALID_UTF8_ENCODING]: 'Invalid UTF-8 encoding',\n [BudgetSMSErrorCode.INVALID_SMS_ID]: 'Invalid SMSid',\n\n [BudgetSMSErrorCode.NO_ROUTE_TO_DESTINATION]: 'No route to destination. Contact BudgetSMS for possible solutions',\n [BudgetSMSErrorCode.NO_ROUTES_SETUP]: 'No routes are setup. Contact BudgetSMS for a route setup',\n [BudgetSMSErrorCode.INVALID_DESTINATION]: 'Invalid destination. Check international mobile number formatting',\n\n [BudgetSMSErrorCode.SYSTEM_ERROR_CUSTOM_ID]: 'System error, related to customID',\n [BudgetSMSErrorCode.SYSTEM_ERROR_TEMPORARY]: 'System error, temporary issue. Try resubmitting in 2 to 3 minutes',\n [BudgetSMSErrorCode.SYSTEM_ERROR_TEMPORARY_2]: 'System error, temporary issue',\n [BudgetSMSErrorCode.SYSTEM_ERROR_CONTACT_SUPPORT]: 'System error, temporary issue. Contact BudgetSMS',\n [BudgetSMSErrorCode.SYSTEM_ERROR_PERMANENT]: 'System error, permanent',\n [BudgetSMSErrorCode.GATEWAY_NOT_REACHABLE]: 'Gateway not reachable',\n [BudgetSMSErrorCode.SYSTEM_ERROR_CONTACT_SUPPORT_2]: 'System error, contact BudgetSMS',\n\n [BudgetSMSErrorCode.SEND_ERROR]: 'Send error, Contact BudgetSMS with the send details',\n [BudgetSMSErrorCode.WRONG_SMS_TYPE]: 'Wrong SMS type',\n [BudgetSMSErrorCode.WRONG_OPERATOR]: 'Wrong operator',\n\n [BudgetSMSErrorCode.UNKNOWN_ERROR]: 'Unknown error',\n\n [BudgetSMSErrorCode.NO_HLR_PROVIDER]: 'No HLR provider present, Contact BudgetSMS',\n [BudgetSMSErrorCode.UNEXPECTED_HLR_RESULTS]: 'Unexpected results from HLR provider',\n [BudgetSMSErrorCode.BAD_NUMBER_FORMAT]: 'Bad number format',\n [BudgetSMSErrorCode.HLR_UNEXPECTED_ERROR]: 'Unexpected error. Contact BudgetSMS',\n [BudgetSMSErrorCode.HLR_PROVIDER_ERROR]: 'HLR provider error. Contact BudgetSMS',\n [BudgetSMSErrorCode.HLR_PROVIDER_ERROR_2]: 'HLR provider error. Contact BudgetSMS',\n};\n\n/**\n * DLR (Delivery Report) Status Codes\n * Source: HTTP API Specification V2.7, Chapter 12\n */\nexport enum DLRStatus {\n /** Message is sent, no status yet (default) */\n SENT_NO_STATUS = 0,\n /** Message is delivered */\n DELIVERED = 1,\n /** Message is not sent */\n NOT_SENT = 2,\n /** Message delivery failed */\n DELIVERY_FAILED = 3,\n /** Message is sent */\n SENT = 4,\n /** Message expired */\n EXPIRED = 5,\n /** Message has a invalid destination address */\n INVALID_DESTINATION = 6,\n /** SMSC error, message could not be processed */\n SMSC_ERROR = 7,\n /** Message is not allowed */\n NOT_ALLOWED = 8,\n /** Message status unknown, usually after 24 hours without status update SMSC */\n STATUS_UNKNOWN_24H = 11,\n /** Message status unknown, SMSC received unknown status code */\n STATUS_UNKNOWN_CODE = 12,\n /** Message status unknown, no status update received from SMSC after 72 hours after submit */\n STATUS_UNKNOWN_72H = 13,\n}\n\n/**\n * DLR status descriptions for better understanding\n */\nexport const DLR_STATUS_MESSAGES: Record<DLRStatus, string> = {\n [DLRStatus.SENT_NO_STATUS]: 'Message is sent, no status yet',\n [DLRStatus.DELIVERED]: 'Message is delivered',\n [DLRStatus.NOT_SENT]: 'Message is not sent',\n [DLRStatus.DELIVERY_FAILED]: 'Message delivery failed',\n [DLRStatus.SENT]: 'Message is sent',\n [DLRStatus.EXPIRED]: 'Message expired',\n [DLRStatus.INVALID_DESTINATION]: 'Message has invalid destination address',\n [DLRStatus.SMSC_ERROR]: 'SMSC error, message could not be processed',\n [DLRStatus.NOT_ALLOWED]: 'Message is not allowed',\n [DLRStatus.STATUS_UNKNOWN_24H]: 'Message status unknown, usually after 24 hours without status update from SMSC',\n [DLRStatus.STATUS_UNKNOWN_CODE]: 'Message status unknown, SMSC received unknown status code',\n [DLRStatus.STATUS_UNKNOWN_72H]: 'Message status unknown, no status update received from SMSC after 72 hours',\n};\n","import { BudgetSMSErrorCode, ERROR_MESSAGES } from './constants';\n\n/**\n * Custom error class for BudgetSMS API errors\n */\nexport class BudgetSMSError extends Error {\n /**\n * Creates a new BudgetSMSError\n * @param code - The BudgetSMS error code\n * @param message - Optional custom error message (defaults to standard message for the code)\n */\n constructor(\n public readonly code: BudgetSMSErrorCode,\n message?: string\n ) {\n super(message || ERROR_MESSAGES[code] || `BudgetSMS API error: ${code}`);\n this.name = 'BudgetSMSError';\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, BudgetSMSError);\n }\n }\n\n /**\n * Returns true if the error code indicates a temporary/retryable error\n */\n isRetryable(): boolean {\n return [\n BudgetSMSErrorCode.SYSTEM_ERROR_TEMPORARY,\n BudgetSMSErrorCode.SYSTEM_ERROR_TEMPORARY_2,\n BudgetSMSErrorCode.GATEWAY_NOT_REACHABLE,\n ].includes(this.code);\n }\n\n /**\n * Returns true if the error code indicates an authentication/credentials issue\n */\n isAuthenticationError(): boolean {\n return [\n BudgetSMSErrorCode.INVALID_CREDENTIALS,\n BudgetSMSErrorCode.ACCOUNT_NOT_ACTIVE,\n BudgetSMSErrorCode.IP_NOT_ALLOWED,\n BudgetSMSErrorCode.NO_HANDLE_PROVIDED,\n BudgetSMSErrorCode.NO_USERID_PROVIDED,\n BudgetSMSErrorCode.NO_USERNAME_PROVIDED,\n ].includes(this.code);\n }\n\n /**\n * Returns true if the error code indicates insufficient credits\n */\n isInsufficientCredits(): boolean {\n return this.code === BudgetSMSErrorCode.NOT_ENOUGH_CREDITS;\n }\n\n /**\n * Convert error to JSON for logging/serialization\n */\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n stack: this.stack,\n };\n }\n}\n","import { BudgetSMSError } from './errors';\nimport { BudgetSMSErrorCode, DLRStatus } from './constants';\nimport type {\n APIRequestParams,\n SendSMSResponse,\n CheckCreditResponse,\n OperatorResponse,\n SMSStatusResponse,\n GetPricingResponse,\n} from './types';\n\n/**\n * Build a query string from parameters with proper UTF-8 URL encoding\n * @param params - Object containing query parameters\n * @returns URL-encoded query string\n */\nexport function buildQueryString(params: APIRequestParams): string {\n const pairs: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n // Convert booleans to 1/0 as expected by the API\n const stringValue = typeof value === 'boolean' ? (value ? '1' : '0') : String(value);\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(stringValue)}`);\n }\n }\n\n return pairs.join('&');\n}\n\n/**\n * Parse a basic API response (OK/ERR format)\n * @param response - Raw response text from API\n * @returns Parsed response data or throws BudgetSMSError\n */\nexport function parseResponse(response: string): string {\n const trimmed = response.trim();\n\n // Check for error response\n if (trimmed.startsWith('ERR ')) {\n const errorCode = parseInt(trimmed.substring(4), 10);\n if (isNaN(errorCode)) {\n throw new Error(`Invalid error response format: ${trimmed}`);\n }\n throw new BudgetSMSError(errorCode as BudgetSMSErrorCode);\n }\n\n // Check for success response\n if (trimmed.startsWith('OK ')) {\n return trimmed.substring(3).trim();\n }\n\n if (trimmed === 'OK') {\n return '';\n }\n\n throw new Error(`Unexpected API response format: ${trimmed}`);\n}\n\n/**\n * Parse Send SMS response with optional price and mccmnc data\n * Format: \"OK smsId [price parts] [mccMnc]\"\n * @param response - Raw response text from API\n * @param includePrice - Whether price info was requested\n * @param includeMccMnc - Whether mccmnc info was requested\n * @param includeCredit - Whether credit info was requested\n * @returns Parsed SendSMSResponse object\n */\nexport function parseSendSMSResponse(\n response: string,\n includePrice?: boolean,\n includeMccMnc?: boolean,\n includeCredit?: boolean\n): SendSMSResponse {\n const data = parseResponse(response);\n const parts = data.split(/\\s+/);\n\n if (parts.length === 0) {\n throw new Error('Invalid send SMS response: no SMS ID found');\n }\n\n const result: SendSMSResponse = {\n success: true,\n smsId: parts[0],\n };\n\n let index = 1;\n\n // Parse price and parts if requested\n if (includePrice && parts.length > index + 1) {\n result.price = parseFloat(parts[index]);\n result.parts = parseInt(parts[index + 1], 10);\n index += 2;\n }\n\n // Parse mccMnc if requested\n if (includeMccMnc && parts.length > index) {\n result.mccMnc = parts[index];\n index += 1;\n }\n\n // Parse credit if requested\n if (includeCredit && parts.length > index) {\n result.credit = parseFloat(parts[index]);\n }\n\n return result;\n}\n\n/**\n * Parse check credit response\n * Format: \"OK credit\"\n * @param response - Raw response text from API\n * @returns Parsed CheckCreditResponse object\n */\nexport function parseCheckCreditResponse(response: string): CheckCreditResponse {\n const data = parseResponse(response);\n const credit = parseFloat(data);\n\n if (isNaN(credit)) {\n throw new Error(`Invalid credit response: ${data}`);\n }\n\n return {\n success: true,\n credit,\n };\n}\n\n/**\n * Parse operator or HLR response\n * Format: \"OK:mccMnc:operatorName:messageCost\"\n * @param response - Raw response text from API\n * @returns Parsed OperatorResponse object\n */\nexport function parseOperatorResponse(response: string): OperatorResponse {\n const data = parseResponse(response);\n const parts = data.split(':');\n\n if (parts.length < 3) {\n throw new Error(`Invalid operator response format: ${data}`);\n }\n\n return {\n success: true,\n mccMnc: parts[0],\n operatorName: parts[1],\n messageCost: parseFloat(parts[2]),\n };\n}\n\n/**\n * Parse SMS status check response\n * Format: \"OK status\"\n * @param response - Raw response text from API\n * @param smsId - The SMS ID that was checked\n * @returns Parsed SMSStatusResponse object\n */\nexport function parseSMSStatusResponse(response: string, smsId: string): SMSStatusResponse {\n const data = parseResponse(response);\n const status = parseInt(data, 10);\n\n if (isNaN(status)) {\n throw new Error(`Invalid status response: ${data}`);\n }\n\n return {\n success: true,\n smsId,\n status: status as DLRStatus,\n };\n}\n\n/**\n * Parse pricing response (JSON format)\n * @param response - Raw JSON response from API\n * @returns Parsed GetPricingResponse array\n */\nexport function parsePricingResponse(response: string): GetPricingResponse {\n // Check for error response first\n if (response.trim().startsWith('ERR ')) {\n parseResponse(response); // This will throw the appropriate error\n }\n\n try {\n const pricing = JSON.parse(response);\n if (!Array.isArray(pricing)) {\n throw new Error('Pricing response is not an array');\n }\n return pricing;\n } catch (error) {\n if (error instanceof BudgetSMSError) {\n throw error;\n }\n throw new Error(`Failed to parse pricing response: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\n/**\n * Validate phone number format (basic MSISDN validation)\n * @param phoneNumber - Phone number to validate\n * @returns true if valid, false otherwise\n */\nexport function validatePhoneNumber(phoneNumber: string): boolean {\n // Must be numeric and between 8-16 digits\n return /^\\d{8,16}$/.test(phoneNumber);\n}\n\n/**\n * Validate sender ID format\n * @param sender - Sender ID to validate\n * @returns true if valid, false otherwise\n */\nexport function validateSender(sender: string): boolean {\n // Alphanumeric: max 11 characters [a-zA-Z0-9]\n if (/^[a-zA-Z0-9]{1,11}$/.test(sender)) {\n return true;\n }\n\n // Numeric: max 16 digits\n if (/^\\d{1,16}$/.test(sender)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Validate message text\n * @param message - Message text to validate\n * @returns true if valid, false otherwise\n */\nexport function validateMessage(message: string): boolean {\n // Must not be empty and should be reasonable length (max 612 chars for 4 SMS parts)\n return message.length > 0 && message.length <= 612;\n}\n","import { API_BASE, ENDPOINTS } from './constants';\nimport type {\n BudgetSMSConfig,\n SendSMSParams,\n TestSMSParams,\n SendSMSResponse,\n TestSMSResponse,\n CheckCreditResponse,\n OperatorResponse,\n HLRResponse,\n SMSStatusResponse,\n GetPricingResponse,\n APIRequestParams,\n} from './types';\nimport {\n buildQueryString,\n parseSendSMSResponse,\n parseCheckCreditResponse,\n parseOperatorResponse,\n parseSMSStatusResponse,\n parsePricingResponse,\n} from './utils';\n\n/**\n * BudgetSMS API Client\n *\n * A modern, type-safe client for the BudgetSMS.net HTTP API.\n * Supports all API endpoints with proper error handling and response parsing.\n *\n * @example\n * ```typescript\n * const client = new BudgetSMS({\n * username: 'your-username',\n * userid: 'your-userid',\n * handle: 'your-api-handle'\n * });\n *\n * // Send an SMS\n * const result = await client.sendSMS({\n * msg: 'Hello World!',\n * from: 'YourApp',\n * to: '31612345678'\n * });\n * ```\n */\nexport class BudgetSMS {\n private readonly username: string;\n private readonly userid: string;\n private readonly handle: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n /**\n * Create a new BudgetSMS client\n * @param config - Configuration object with credentials and optional settings\n */\n constructor(config: BudgetSMSConfig) {\n this.username = config.username;\n this.userid = config.userid;\n this.handle = config.handle;\n this.baseUrl = config.baseUrl || API_BASE;\n this.timeout = config.timeout || 30000;\n }\n\n /**\n * Make an HTTP GET request to the API\n * @param endpoint - API endpoint path\n * @param params - Query parameters\n * @returns Response text\n */\n private async request(endpoint: string, params: APIRequestParams = {}): Promise<string> {\n const queryString = buildQueryString(params);\n const url = `${this.baseUrl}${endpoint}?${queryString}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n return await response.text();\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timeout after ${this.timeout}ms`);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Get base authentication parameters\n */\n private getAuthParams(): APIRequestParams {\n return {\n username: this.username,\n userid: this.userid,\n handle: this.handle,\n };\n }\n\n /**\n * Send an SMS message\n *\n * @param params - SMS parameters\n * @returns Promise resolving to SendSMSResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.sendSMS({\n * msg: 'Hello World!',\n * from: 'YourApp',\n * to: '31612345678',\n * price: true, // Get price info in response\n * mccmnc: true // Get operator info in response\n * });\n *\n * console.log(`SMS sent with ID: ${result.smsId}`);\n * if (result.price) {\n * console.log(`Cost: €${result.price} for ${result.parts} part(s)`);\n * }\n * ```\n */\n async sendSMS(params: SendSMSParams): Promise<SendSMSResponse> {\n const requestParams: APIRequestParams = {\n ...this.getAuthParams(),\n msg: params.msg,\n from: params.from,\n to: params.to,\n customid: params.customid,\n price: params.price,\n mccmnc: params.mccmnc,\n credit: params.credit,\n };\n\n const response = await this.request(ENDPOINTS.SEND_SMS, requestParams);\n return parseSendSMSResponse(response, params.price, params.mccmnc, params.credit);\n }\n\n /**\n * Test SMS sending without actually sending or reducing credit\n *\n * Useful for testing your implementation without consuming credits.\n *\n * @param params - SMS parameters (same as sendSMS)\n * @returns Promise resolving to TestSMSResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.testSMS({\n * msg: 'Test message',\n * from: 'TestApp',\n * to: '31612345678'\n * });\n *\n * console.log(`Test successful, would get SMS ID: ${result.smsId}`);\n * ```\n */\n async testSMS(params: TestSMSParams): Promise<TestSMSResponse> {\n const requestParams: APIRequestParams = {\n ...this.getAuthParams(),\n msg: params.msg,\n from: params.from,\n to: params.to,\n customid: params.customid,\n price: params.price,\n mccmnc: params.mccmnc,\n credit: params.credit,\n };\n\n const response = await this.request(ENDPOINTS.TEST_SMS, requestParams);\n return parseSendSMSResponse(response, params.price, params.mccmnc, params.credit);\n }\n\n /**\n * Check remaining account credit\n *\n * @returns Promise resolving to CheckCreditResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.checkCredit();\n * console.log(`Remaining credit: €${result.credit}`);\n * ```\n */\n async checkCredit(): Promise<CheckCreditResponse> {\n const response = await this.request(ENDPOINTS.CHECK_CREDIT, this.getAuthParams());\n return parseCheckCreditResponse(response);\n }\n\n /**\n * Check operator based on phone number prefix\n *\n * Note: This checks the original operator based on prefix.\n * If a number has been ported, use hlr() instead.\n *\n * @param phoneNumber - Phone number to check (international format, no +)\n * @returns Promise resolving to OperatorResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.checkOperator('31612345678');\n * console.log(`Operator: ${result.operatorName} (${result.mccMnc})`);\n * console.log(`Cost: €${result.messageCost}`);\n * ```\n */\n async checkOperator(phoneNumber: string): Promise<OperatorResponse> {\n const requestParams: APIRequestParams = {\n ...this.getAuthParams(),\n check: phoneNumber,\n };\n\n const response = await this.request(ENDPOINTS.CHECK_OPERATOR, requestParams);\n return parseOperatorResponse(response);\n }\n\n /**\n * Perform HLR (Home Location Register) lookup\n *\n * Returns the actual current operator, even if the number has been ported.\n * More accurate than checkOperator() but may cost credits.\n *\n * @param phoneNumber - Phone number to lookup (international format, no +)\n * @returns Promise resolving to HLRResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.hlr('31612345678');\n * console.log(`Current operator: ${result.operatorName}`);\n * console.log(`Network: ${result.mccMnc}`);\n * ```\n */\n async hlr(phoneNumber: string): Promise<HLRResponse> {\n const requestParams: APIRequestParams = {\n ...this.getAuthParams(),\n to: phoneNumber,\n };\n\n const response = await this.request(ENDPOINTS.HLR, requestParams);\n return parseOperatorResponse(response);\n }\n\n /**\n * Check SMS delivery status (Pull DLR)\n *\n * Retrieve the current delivery status of a sent message.\n * For automatic updates, consider using Push DLR instead.\n *\n * @param smsId - The SMS ID returned from sendSMS()\n * @returns Promise resolving to SMSStatusResponse\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const result = await client.checkSMS('12345678');\n * console.log(`Status: ${result.status}`); // DLRStatus enum value\n * ```\n */\n async checkSMS(smsId: string): Promise<SMSStatusResponse> {\n const requestParams: APIRequestParams = {\n ...this.getAuthParams(),\n smsid: smsId,\n };\n\n const response = await this.request(ENDPOINTS.CHECK_SMS, requestParams);\n return parseSMSStatusResponse(response, smsId);\n }\n\n /**\n * Get account pricing for all operators\n *\n * Returns a comprehensive list of pricing for all available operators.\n * Each entry includes country, operator, MCC/MNC codes, and pricing info.\n *\n * @returns Promise resolving to GetPricingResponse (array of pricing entries)\n * @throws {BudgetSMSError} If the API returns an error\n *\n * @example\n * ```typescript\n * const pricing = await client.getPricing();\n * for (const entry of pricing) {\n * console.log(`${entry.countryname} - ${entry.operatorname}: €${entry.price}`);\n * }\n * ```\n */\n async getPricing(): Promise<GetPricingResponse> {\n const response = await this.request(ENDPOINTS.GET_PRICING, this.getAuthParams());\n return parsePricingResponse(response);\n }\n}\n"]}
|