@beep-it/sdk-core 0.1.7 → 0.2.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/dist/index.js CHANGED
@@ -28,16 +28,48 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BeepAuthenticationError: () => BeepAuthenticationError,
33
34
  BeepClient: () => BeepClient,
35
+ BeepError: () => BeepError,
36
+ BeepErrorCode: () => BeepErrorCode,
37
+ BeepNetworkError: () => BeepNetworkError,
38
+ BeepPaymentError: () => BeepPaymentError,
34
39
  BeepPublicClient: () => BeepPublicClient,
40
+ BeepRateLimitError: () => BeepRateLimitError,
41
+ BeepValidationError: () => BeepValidationError,
42
+ InvoiceStatus: () => InvoiceStatus,
43
+ PayoutStatus: () => PayoutStatus,
35
44
  SupportedToken: () => SupportedToken,
36
- TokenUtils: () => TokenUtils
45
+ TOKEN_ADDRESSES: () => TOKEN_ADDRESSES,
46
+ TOKEN_DECIMALS: () => TOKEN_DECIMALS,
47
+ TokenUtils: () => TokenUtils,
48
+ createBeepErrorFromAxios: () => createBeepErrorFromAxios
37
49
  });
38
- module.exports = __toCommonJS(src_exports);
50
+ module.exports = __toCommonJS(index_exports);
39
51
  var import_axios = __toESM(require("axios"));
40
52
 
53
+ // src/types/invoice.ts
54
+ var InvoiceStatus = /* @__PURE__ */ ((InvoiceStatus2) => {
55
+ InvoiceStatus2["PENDING"] = "pending";
56
+ InvoiceStatus2["PAID"] = "paid";
57
+ InvoiceStatus2["CONFIRMED"] = "confirmed";
58
+ InvoiceStatus2["EXPIRED"] = "expired";
59
+ InvoiceStatus2["FAILED"] = "failed";
60
+ return InvoiceStatus2;
61
+ })(InvoiceStatus || {});
62
+
63
+ // src/types/payment.ts
64
+ var PayoutStatus = /* @__PURE__ */ ((PayoutStatus2) => {
65
+ PayoutStatus2["PENDING"] = "PENDING";
66
+ PayoutStatus2["IN_PROGRESS"] = "IN_PROGRESS";
67
+ PayoutStatus2["COMPLETED"] = "COMPLETED";
68
+ PayoutStatus2["FAILED"] = "FAILED";
69
+ PayoutStatus2["CANCELED"] = "CANCELED";
70
+ return PayoutStatus2;
71
+ })(PayoutStatus || {});
72
+
41
73
  // src/types/token.ts
42
74
  var SupportedToken = /* @__PURE__ */ ((SupportedToken3) => {
43
75
  SupportedToken3["USDC"] = "USDC";
@@ -149,11 +181,11 @@ var InvoicesModule = class {
149
181
  /**
150
182
  * Creates a new invoice for payment processing
151
183
  * Supports both product-based invoices (linked to existing products) and custom invoices
152
- *
184
+ *
153
185
  * @param payload - Invoice creation parameters (product-based or custom)
154
186
  * @returns Promise that resolves to the created invoice
155
187
  * @throws {Error} When invoice creation fails
156
- *
188
+ *
157
189
  * @example
158
190
  * ```typescript
159
191
  * // Create invoice from existing product
@@ -161,7 +193,7 @@ var InvoicesModule = class {
161
193
  * productId: 'prod_123',
162
194
  * payerType: 'customer_wallet'
163
195
  * });
164
- *
196
+ *
165
197
  * // Create custom invoice
166
198
  * const customInvoice = await beep.invoices.createInvoice({
167
199
  * description: 'Consulting services',
@@ -174,18 +206,20 @@ var InvoicesModule = class {
174
206
  async createInvoice(payload) {
175
207
  const requestPayload = { ...payload };
176
208
  if ("token" in requestPayload && !("splTokenAddress" in requestPayload)) {
177
- requestPayload.splTokenAddress = TokenUtils.getTokenAddress(requestPayload.token);
209
+ requestPayload.splTokenAddress = TokenUtils.getTokenAddress(
210
+ requestPayload.token
211
+ );
178
212
  }
179
213
  const response = await this.client.post("/v1/invoices", requestPayload);
180
214
  return response.data;
181
215
  }
182
216
  /**
183
217
  * Retrieves a specific invoice by its ID
184
- *
218
+ *
185
219
  * @param invoiceId - The unique identifier of the invoice to retrieve
186
220
  * @returns Promise that resolves to the invoice details
187
221
  * @throws {Error} When the invoice is not found or retrieval fails
188
- *
222
+ *
189
223
  * @example
190
224
  * ```typescript
191
225
  * const invoice = await beep.invoices.getInvoice('inv_123abc456def');
@@ -199,10 +233,10 @@ var InvoicesModule = class {
199
233
  }
200
234
  /**
201
235
  * Retrieves all invoices for the current merchant
202
- *
236
+ *
203
237
  * @returns Promise that resolves to an array of invoices
204
238
  * @throws {Error} When invoice retrieval fails
205
- *
239
+ *
206
240
  * @example
207
241
  * ```typescript
208
242
  * const invoices = await beep.invoices.listInvoices();
@@ -216,13 +250,13 @@ var InvoicesModule = class {
216
250
  }
217
251
  /**
218
252
  * Deletes an existing invoice
219
- *
253
+ *
220
254
  * @param invoiceId - The unique identifier of the invoice to delete
221
255
  * @returns Promise that resolves when the invoice is successfully deleted
222
256
  * @throws {Error} When the invoice is not found or deletion fails
223
- *
257
+ *
224
258
  * @remarks Once deleted, an invoice cannot be recovered. Use with caution.
225
- *
259
+ *
226
260
  * @example
227
261
  * ```typescript
228
262
  * await beep.invoices.deleteInvoice('inv_123abc456def');
@@ -234,6 +268,211 @@ var InvoicesModule = class {
234
268
  }
235
269
  };
236
270
 
271
+ // src/errors/index.ts
272
+ var BeepErrorCode = /* @__PURE__ */ ((BeepErrorCode2) => {
273
+ BeepErrorCode2["INVALID_API_KEY"] = "BEEP_1001";
274
+ BeepErrorCode2["MISSING_API_KEY"] = "BEEP_1002";
275
+ BeepErrorCode2["UNAUTHORIZED"] = "BEEP_1003";
276
+ BeepErrorCode2["INVALID_PUBLISHABLE_KEY"] = "BEEP_1004";
277
+ BeepErrorCode2["NETWORK_ERROR"] = "BEEP_2001";
278
+ BeepErrorCode2["TIMEOUT"] = "BEEP_2002";
279
+ BeepErrorCode2["SERVER_ERROR"] = "BEEP_2003";
280
+ BeepErrorCode2["PAYMENT_FAILED"] = "BEEP_3001";
281
+ BeepErrorCode2["PAYMENT_EXPIRED"] = "BEEP_3002";
282
+ BeepErrorCode2["PAYMENT_NOT_FOUND"] = "BEEP_3003";
283
+ BeepErrorCode2["INSUFFICIENT_FUNDS"] = "BEEP_3004";
284
+ BeepErrorCode2["PAYMENT_ALREADY_PROCESSED"] = "BEEP_3005";
285
+ BeepErrorCode2["INVOICE_NOT_FOUND"] = "BEEP_4001";
286
+ BeepErrorCode2["INVOICE_EXPIRED"] = "BEEP_4002";
287
+ BeepErrorCode2["INVOICE_ALREADY_PAID"] = "BEEP_4003";
288
+ BeepErrorCode2["INVALID_PARAMETER"] = "BEEP_5001";
289
+ BeepErrorCode2["MISSING_PARAMETER"] = "BEEP_5002";
290
+ BeepErrorCode2["INVALID_AMOUNT"] = "BEEP_5003";
291
+ BeepErrorCode2["INVALID_TOKEN"] = "BEEP_5004";
292
+ BeepErrorCode2["RATE_LIMIT_EXCEEDED"] = "BEEP_6001";
293
+ BeepErrorCode2["UNKNOWN_ERROR"] = "BEEP_9999";
294
+ return BeepErrorCode2;
295
+ })(BeepErrorCode || {});
296
+ var BeepError = class _BeepError extends Error {
297
+ constructor(message, options) {
298
+ super(message);
299
+ this.name = "BeepError";
300
+ this.code = options.code;
301
+ this.statusCode = options.statusCode;
302
+ this.details = options.details;
303
+ this.timestamp = /* @__PURE__ */ new Date();
304
+ this.requestId = options.requestId;
305
+ if (Error.captureStackTrace) {
306
+ Error.captureStackTrace(this, _BeepError);
307
+ }
308
+ }
309
+ /**
310
+ * Returns a user-friendly error message
311
+ */
312
+ getUserMessage() {
313
+ switch (this.code) {
314
+ case "BEEP_1001" /* INVALID_API_KEY */:
315
+ return "The API key provided is invalid. Please check your credentials.";
316
+ case "BEEP_1002" /* MISSING_API_KEY */:
317
+ return "No API key provided. Please provide a valid API key.";
318
+ case "BEEP_2001" /* NETWORK_ERROR */:
319
+ return "Unable to connect to BEEP servers. Please check your internet connection.";
320
+ case "BEEP_3002" /* PAYMENT_EXPIRED */:
321
+ return "This payment request has expired. Please create a new one.";
322
+ case "BEEP_3004" /* INSUFFICIENT_FUNDS */:
323
+ return "Insufficient funds to complete this transaction.";
324
+ case "BEEP_6001" /* RATE_LIMIT_EXCEEDED */:
325
+ return "Too many requests. Please try again later.";
326
+ default:
327
+ return this.message || "An unexpected error occurred.";
328
+ }
329
+ }
330
+ /**
331
+ * Returns a JSON representation of the error for logging
332
+ */
333
+ toJSON() {
334
+ return {
335
+ name: this.name,
336
+ message: this.message,
337
+ code: this.code,
338
+ statusCode: this.statusCode,
339
+ details: this.details,
340
+ timestamp: this.timestamp,
341
+ requestId: this.requestId,
342
+ stack: this.stack
343
+ };
344
+ }
345
+ };
346
+ var BeepAuthenticationError = class extends BeepError {
347
+ constructor(message, options = {}) {
348
+ super(message, {
349
+ code: options.code ?? "BEEP_1003" /* UNAUTHORIZED */,
350
+ statusCode: 401,
351
+ details: options.details
352
+ });
353
+ this.name = "BeepAuthenticationError";
354
+ }
355
+ };
356
+ var BeepValidationError = class extends BeepError {
357
+ constructor(message, options = {}) {
358
+ super(message, {
359
+ code: options.code ?? "BEEP_5001" /* INVALID_PARAMETER */,
360
+ statusCode: 400,
361
+ details: options.details
362
+ });
363
+ this.name = "BeepValidationError";
364
+ }
365
+ };
366
+ var BeepPaymentError = class extends BeepError {
367
+ constructor(message, options = {}) {
368
+ super(message, {
369
+ code: options.code ?? "BEEP_3001" /* PAYMENT_FAILED */,
370
+ statusCode: 402,
371
+ details: options.details
372
+ });
373
+ this.name = "BeepPaymentError";
374
+ }
375
+ };
376
+ var BeepNetworkError = class extends BeepError {
377
+ constructor(message, options = {}) {
378
+ super(message, {
379
+ code: options.code ?? "BEEP_2001" /* NETWORK_ERROR */,
380
+ details: options.details
381
+ });
382
+ this.name = "BeepNetworkError";
383
+ }
384
+ };
385
+ var BeepRateLimitError = class extends BeepError {
386
+ constructor(message, options = {}) {
387
+ super(message, {
388
+ code: "BEEP_6001" /* RATE_LIMIT_EXCEEDED */,
389
+ statusCode: 429,
390
+ details: options.details
391
+ });
392
+ this.name = "BeepRateLimitError";
393
+ this.retryAfter = options.retryAfter;
394
+ }
395
+ };
396
+ function createBeepErrorFromAxios(error) {
397
+ const response = error.response;
398
+ const requestId = response?.headers?.["x-request-id"];
399
+ if (!response) {
400
+ return new BeepNetworkError(error.message || "Network connection failed", {
401
+ code: "BEEP_2001" /* NETWORK_ERROR */,
402
+ details: { originalError: error }
403
+ });
404
+ }
405
+ const status = response.status;
406
+ const data = response.data;
407
+ const message = data?.message || data?.error || error.message;
408
+ switch (status) {
409
+ case 401:
410
+ return new BeepAuthenticationError(message, {
411
+ code: "BEEP_1003" /* UNAUTHORIZED */,
412
+ details: { response: data }
413
+ });
414
+ case 400: {
415
+ if (message.toLowerCase().includes("api key")) {
416
+ return new BeepAuthenticationError(message, {
417
+ code: "BEEP_1001" /* INVALID_API_KEY */,
418
+ details: { response: data }
419
+ });
420
+ }
421
+ return new BeepValidationError(message, {
422
+ code: "BEEP_5001" /* INVALID_PARAMETER */,
423
+ details: { response: data, fields: data?.fields }
424
+ });
425
+ }
426
+ case 402:
427
+ return new BeepPaymentError(message, {
428
+ code: "BEEP_3001" /* PAYMENT_FAILED */,
429
+ details: { response: data }
430
+ });
431
+ case 404: {
432
+ if (message.toLowerCase().includes("invoice")) {
433
+ return new BeepError(message, {
434
+ code: "BEEP_4001" /* INVOICE_NOT_FOUND */,
435
+ statusCode: 404,
436
+ details: { response: data },
437
+ requestId
438
+ });
439
+ }
440
+ if (message.toLowerCase().includes("payment")) {
441
+ return new BeepError(message, {
442
+ code: "BEEP_3003" /* PAYMENT_NOT_FOUND */,
443
+ statusCode: 404,
444
+ details: { response: data },
445
+ requestId
446
+ });
447
+ }
448
+ break;
449
+ }
450
+ case 429: {
451
+ const retryAfter = response.headers?.["retry-after"];
452
+ return new BeepRateLimitError(message, {
453
+ retryAfter: retryAfter ? parseInt(retryAfter) : void 0,
454
+ details: { response: data }
455
+ });
456
+ }
457
+ case 500:
458
+ case 502:
459
+ case 503:
460
+ case 504:
461
+ return new BeepError(message, {
462
+ code: "BEEP_2003" /* SERVER_ERROR */,
463
+ statusCode: status,
464
+ details: { response: data },
465
+ requestId
466
+ });
467
+ }
468
+ return new BeepError(message, {
469
+ code: "BEEP_9999" /* UNKNOWN_ERROR */,
470
+ statusCode: status,
471
+ details: { response: data },
472
+ requestId
473
+ });
474
+ }
475
+
237
476
  // src/modules/payments.ts
238
477
  var PaymentsModule = class {
239
478
  constructor(client) {
@@ -407,12 +646,13 @@ var PaymentsModule = class {
407
646
  input
408
647
  );
409
648
  if (!response.data || !response.data.data) {
410
- throw new Error("No data returned from solana transaction signing");
649
+ throw new BeepPaymentError("No data returned from solana transaction signing", {
650
+ code: "BEEP_3001" /* PAYMENT_FAILED */
651
+ });
411
652
  }
412
653
  return response.data.data;
413
654
  } catch (error) {
414
- const errorMessage = error instanceof Error ? error.message : String(error);
415
- throw new Error(`Failed to sign solana transaction: ${errorMessage}`);
655
+ throw createBeepErrorFromAxios(error);
416
656
  }
417
657
  }
418
658
  // --- Streaming Payment Methods ---
@@ -808,6 +1048,176 @@ var UserModule = class {
808
1048
  }
809
1049
  };
810
1050
 
1051
+ // src/utils/debug.ts
1052
+ var defaultLogger = (options) => {
1053
+ const { level, message, data } = options;
1054
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1055
+ const prefix = `[BEEP SDK ${level}] ${timestamp}`;
1056
+ switch (level) {
1057
+ case "error":
1058
+ console.error(prefix, message, data);
1059
+ break;
1060
+ case "warn":
1061
+ console.warn(prefix, message, data);
1062
+ break;
1063
+ case "info":
1064
+ console.info(prefix, message, data);
1065
+ break;
1066
+ case "debug":
1067
+ console.debug(prefix, message, data);
1068
+ break;
1069
+ default:
1070
+ console.log(prefix, message, data);
1071
+ }
1072
+ };
1073
+ var BeepDebugger = class {
1074
+ constructor(options = {}) {
1075
+ this.options = options;
1076
+ this.logger = options.logger || defaultLogger;
1077
+ }
1078
+ /**
1079
+ * Log an error with context
1080
+ */
1081
+ error(message, error) {
1082
+ if (error instanceof BeepError) {
1083
+ this.logger({
1084
+ level: "error",
1085
+ message,
1086
+ data: {
1087
+ code: error.code,
1088
+ statusCode: error.statusCode,
1089
+ details: error.details,
1090
+ requestId: error.requestId,
1091
+ userMessage: error.getUserMessage()
1092
+ }
1093
+ });
1094
+ } else {
1095
+ this.logger({ level: "error", message, data: error });
1096
+ }
1097
+ }
1098
+ /**
1099
+ * Log a warning
1100
+ */
1101
+ warn(message, data) {
1102
+ this.logger({ level: "warn", message, data });
1103
+ }
1104
+ /**
1105
+ * Log info message
1106
+ */
1107
+ info(message, data) {
1108
+ if (this.options.debug) {
1109
+ this.logger({ level: "info", message, data });
1110
+ }
1111
+ }
1112
+ /**
1113
+ * Log debug message
1114
+ */
1115
+ debug(message, data) {
1116
+ if (this.options.debug) {
1117
+ this.logger({ level: "debug", message, data });
1118
+ }
1119
+ }
1120
+ /**
1121
+ * Log API request
1122
+ */
1123
+ logRequest(options) {
1124
+ if (this.options.logRequests && this.options.debug) {
1125
+ const { method, url, data } = options;
1126
+ this.logger({
1127
+ level: "debug",
1128
+ message: `API Request: ${method} ${url}`,
1129
+ data: {
1130
+ method,
1131
+ url,
1132
+ data: this.sanitizeData(data)
1133
+ }
1134
+ });
1135
+ }
1136
+ }
1137
+ /**
1138
+ * Log API response
1139
+ */
1140
+ logResponse(options) {
1141
+ if (this.options.logResponses && this.options.debug) {
1142
+ const { method, url, status, data } = options;
1143
+ this.logger({
1144
+ level: "debug",
1145
+ message: `API Response: ${method} ${url} (${status})`,
1146
+ data: {
1147
+ method,
1148
+ url,
1149
+ status,
1150
+ data: this.sanitizeData(data)
1151
+ }
1152
+ });
1153
+ }
1154
+ }
1155
+ /**
1156
+ * Sanitize sensitive data before logging
1157
+ */
1158
+ sanitizeData(data) {
1159
+ if (!data) return data;
1160
+ const sensitiveFields = ["apiKey", "api_key", "authorization", "password", "secret"];
1161
+ if (typeof data === "string") {
1162
+ return data;
1163
+ }
1164
+ if (Array.isArray(data)) {
1165
+ return data.map((item) => this.sanitizeData(item));
1166
+ }
1167
+ if (typeof data === "object") {
1168
+ const sanitized = {};
1169
+ for (const [key, value] of Object.entries(data)) {
1170
+ if (sensitiveFields.some((field) => key.toLowerCase().includes(field))) {
1171
+ sanitized[key] = "[REDACTED]";
1172
+ } else {
1173
+ sanitized[key] = this.sanitizeData(value);
1174
+ }
1175
+ }
1176
+ return sanitized;
1177
+ }
1178
+ return data;
1179
+ }
1180
+ };
1181
+ function createDebugInterceptors(axios2, beepDebugger) {
1182
+ axios2.interceptors.request.use(
1183
+ (config) => {
1184
+ beepDebugger.logRequest({
1185
+ method: config.method?.toUpperCase() || "GET",
1186
+ url: config.url || "",
1187
+ data: config.data
1188
+ });
1189
+ return config;
1190
+ },
1191
+ (error) => {
1192
+ beepDebugger.error("Request interceptor error", error);
1193
+ return Promise.reject(error);
1194
+ }
1195
+ );
1196
+ axios2.interceptors.response.use(
1197
+ (response) => {
1198
+ beepDebugger.logResponse({
1199
+ method: response.config.method?.toUpperCase() || "GET",
1200
+ url: response.config.url || "",
1201
+ status: response.status,
1202
+ data: response.data
1203
+ });
1204
+ return response;
1205
+ },
1206
+ (error) => {
1207
+ if (error.response) {
1208
+ beepDebugger.logResponse({
1209
+ method: error.config?.method?.toUpperCase() || "GET",
1210
+ url: error.config?.url || "",
1211
+ status: error.response.status,
1212
+ data: error.response.data
1213
+ });
1214
+ }
1215
+ beepDebugger.error("API Error", error);
1216
+ return Promise.reject(error);
1217
+ }
1218
+ );
1219
+ }
1220
+
811
1221
  // src/index.ts
812
1222
  var BeepClient = class {
813
1223
  /**
@@ -818,8 +1228,11 @@ var BeepClient = class {
818
1228
  */
819
1229
  constructor(options) {
820
1230
  if (!options.apiKey) {
821
- throw new Error("API key is required to initialize BeepClient");
1231
+ throw new BeepAuthenticationError("API key is required to initialize BeepClient", {
1232
+ code: "BEEP_1002" /* MISSING_API_KEY */
1233
+ });
822
1234
  }
1235
+ this.debugger = new BeepDebugger(options.debug);
823
1236
  this.client = import_axios.default.create({
824
1237
  baseURL: options.serverUrl || "https://api.justbeep.it",
825
1238
  headers: {
@@ -828,6 +1241,9 @@ var BeepClient = class {
828
1241
  "X-Beep-Client": "beep-sdk"
829
1242
  }
830
1243
  });
1244
+ if (options.debug?.debug) {
1245
+ createDebugInterceptors(this.client, this.debugger);
1246
+ }
831
1247
  this.products = new ProductsModule(this.client);
832
1248
  this.invoices = new InvoicesModule(this.client);
833
1249
  this.payments = new PaymentsModule(this.client);
@@ -884,7 +1300,12 @@ var BeepPublicClient = class {
884
1300
  */
885
1301
  constructor(options) {
886
1302
  if (!options.publishableKey) {
887
- throw new Error("publishableKey is required to initialize BeepPublicClient");
1303
+ throw new BeepAuthenticationError(
1304
+ "publishableKey is required to initialize BeepPublicClient",
1305
+ {
1306
+ code: "BEEP_1002" /* MISSING_API_KEY */
1307
+ }
1308
+ );
888
1309
  }
889
1310
  this.client = import_axios.default.create({
890
1311
  baseURL: options.serverUrl || "https://api.justbeep.it",
@@ -899,8 +1320,20 @@ var BeepPublicClient = class {
899
1320
  };
900
1321
  // Annotate the CommonJS export names for ESM import in node:
901
1322
  0 && (module.exports = {
1323
+ BeepAuthenticationError,
902
1324
  BeepClient,
1325
+ BeepError,
1326
+ BeepErrorCode,
1327
+ BeepNetworkError,
1328
+ BeepPaymentError,
903
1329
  BeepPublicClient,
1330
+ BeepRateLimitError,
1331
+ BeepValidationError,
1332
+ InvoiceStatus,
1333
+ PayoutStatus,
904
1334
  SupportedToken,
905
- TokenUtils
1335
+ TOKEN_ADDRESSES,
1336
+ TOKEN_DECIMALS,
1337
+ TokenUtils,
1338
+ createBeepErrorFromAxios
906
1339
  });