@singularity-payments/elysia 0.1.0-alpha.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/dist/index.js ADDED
@@ -0,0 +1,514 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ MpesaClient: () => import_core2.MpesaClient,
24
+ createMpesa: () => createMpesa,
25
+ createMpesaHandlers: () => createMpesaHandlers
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_core = require("@singularity-payments/core");
29
+ var import_elysia = require("elysia");
30
+
31
+ // src/handlers.ts
32
+ function createMpesaHandlers(client) {
33
+ const handlers = {
34
+ stkCallback: async (ctx) => {
35
+ try {
36
+ const body = ctx.body;
37
+ const ipAddress = ctx.request.headers.get("x-forwarded-for") || ctx.request.headers.get("x-real-ip") || void 0;
38
+ const response = await client.handleSTKCallback(body, ipAddress);
39
+ ctx.set.status = 200;
40
+ return response;
41
+ } catch (error) {
42
+ console.error("STK Callback error:", error);
43
+ ctx.set.status = 200;
44
+ return {
45
+ ResultCode: 1,
46
+ ResultDesc: "Internal error processing callback"
47
+ };
48
+ }
49
+ },
50
+ c2bValidation: async (ctx) => {
51
+ try {
52
+ const body = ctx.body;
53
+ const response = await client.handleC2BValidation(body);
54
+ ctx.set.status = 200;
55
+ return response;
56
+ } catch (error) {
57
+ console.error("C2B Validation error:", error);
58
+ ctx.set.status = 200;
59
+ return {
60
+ ResultCode: 1,
61
+ ResultDesc: "Validation failed"
62
+ };
63
+ }
64
+ },
65
+ c2bConfirmation: async (ctx) => {
66
+ try {
67
+ const body = ctx.body;
68
+ const response = await client.handleC2BConfirmation(body);
69
+ ctx.set.status = 200;
70
+ return response;
71
+ } catch (error) {
72
+ console.error("C2B Confirmation error:", error);
73
+ ctx.set.status = 200;
74
+ return {
75
+ ResultCode: 1,
76
+ ResultDesc: "Processing failed"
77
+ };
78
+ }
79
+ },
80
+ b2cResult: async (ctx) => {
81
+ try {
82
+ const body = ctx.body;
83
+ const parsed = client.getCallbackHandler().parseB2CCallback(body);
84
+ console.log("B2C Result:", parsed);
85
+ ctx.set.status = 200;
86
+ return {
87
+ ResultCode: 0,
88
+ ResultDesc: "Accepted"
89
+ };
90
+ } catch (error) {
91
+ console.error("B2C Result error:", error);
92
+ ctx.set.status = 200;
93
+ return {
94
+ ResultCode: 1,
95
+ ResultDesc: "Processing failed"
96
+ };
97
+ }
98
+ },
99
+ b2cTimeout: async (ctx) => {
100
+ try {
101
+ const body = ctx.body;
102
+ console.log("B2C Timeout:", body);
103
+ ctx.set.status = 200;
104
+ return {
105
+ ResultCode: 0,
106
+ ResultDesc: "Timeout received"
107
+ };
108
+ } catch (error) {
109
+ console.error("B2C Timeout error:", error);
110
+ ctx.set.status = 200;
111
+ return {
112
+ ResultCode: 1,
113
+ ResultDesc: "Processing failed"
114
+ };
115
+ }
116
+ },
117
+ b2bResult: async (ctx) => {
118
+ try {
119
+ const body = ctx.body;
120
+ const parsed = client.getCallbackHandler().parseB2BCallback(body);
121
+ console.log("B2B Result:", parsed);
122
+ ctx.set.status = 200;
123
+ return {
124
+ ResultCode: 0,
125
+ ResultDesc: "Accepted"
126
+ };
127
+ } catch (error) {
128
+ console.error("B2B Result error:", error);
129
+ ctx.set.status = 200;
130
+ return {
131
+ ResultCode: 1,
132
+ ResultDesc: "Processing failed"
133
+ };
134
+ }
135
+ },
136
+ b2bTimeout: async (ctx) => {
137
+ try {
138
+ const body = ctx.body;
139
+ console.log("B2B Timeout:", body);
140
+ ctx.set.status = 200;
141
+ return {
142
+ ResultCode: 0,
143
+ ResultDesc: "Timeout received"
144
+ };
145
+ } catch (error) {
146
+ console.error("B2B Timeout error:", error);
147
+ ctx.set.status = 200;
148
+ return {
149
+ ResultCode: 1,
150
+ ResultDesc: "Processing failed"
151
+ };
152
+ }
153
+ },
154
+ balanceResult: async (ctx) => {
155
+ try {
156
+ const body = ctx.body;
157
+ const parsed = client.getCallbackHandler().parseAccountBalanceCallback(body);
158
+ console.log("Balance Result:", parsed);
159
+ ctx.set.status = 200;
160
+ return {
161
+ ResultCode: 0,
162
+ ResultDesc: "Accepted"
163
+ };
164
+ } catch (error) {
165
+ console.error("Balance Result error:", error);
166
+ ctx.set.status = 200;
167
+ return {
168
+ ResultCode: 1,
169
+ ResultDesc: "Processing failed"
170
+ };
171
+ }
172
+ },
173
+ balanceTimeout: async (ctx) => {
174
+ try {
175
+ const body = ctx.body;
176
+ console.log("Balance Timeout:", body);
177
+ ctx.set.status = 200;
178
+ return {
179
+ ResultCode: 0,
180
+ ResultDesc: "Timeout received"
181
+ };
182
+ } catch (error) {
183
+ console.error("Balance Timeout error:", error);
184
+ ctx.set.status = 200;
185
+ return {
186
+ ResultCode: 1,
187
+ ResultDesc: "Processing failed"
188
+ };
189
+ }
190
+ },
191
+ reversalResult: async (ctx) => {
192
+ try {
193
+ const body = ctx.body;
194
+ const parsed = client.getCallbackHandler().parseReversalCallback(body);
195
+ console.log("Reversal Result:", parsed);
196
+ ctx.set.status = 200;
197
+ return {
198
+ ResultCode: 0,
199
+ ResultDesc: "Accepted"
200
+ };
201
+ } catch (error) {
202
+ console.error("Reversal Result error:", error);
203
+ ctx.set.status = 200;
204
+ return {
205
+ ResultCode: 1,
206
+ ResultDesc: "Processing failed"
207
+ };
208
+ }
209
+ },
210
+ reversalTimeout: async (ctx) => {
211
+ try {
212
+ const body = ctx.body;
213
+ console.log("Reversal Timeout:", body);
214
+ ctx.set.status = 200;
215
+ return {
216
+ ResultCode: 0,
217
+ ResultDesc: "Timeout received"
218
+ };
219
+ } catch (error) {
220
+ console.error("Reversal Timeout error:", error);
221
+ ctx.set.status = 200;
222
+ return {
223
+ ResultCode: 1,
224
+ ResultDesc: "Processing failed"
225
+ };
226
+ }
227
+ },
228
+ statusResult: async (ctx) => {
229
+ try {
230
+ const body = ctx.body;
231
+ const parsed = client.getCallbackHandler().parseTransactionStatusCallback(body);
232
+ console.log("Status Result:", parsed);
233
+ ctx.set.status = 200;
234
+ return {
235
+ ResultCode: 0,
236
+ ResultDesc: "Accepted"
237
+ };
238
+ } catch (error) {
239
+ console.error("Status Result error:", error);
240
+ ctx.set.status = 200;
241
+ return {
242
+ ResultCode: 1,
243
+ ResultDesc: "Processing failed"
244
+ };
245
+ }
246
+ },
247
+ statusTimeout: async (ctx) => {
248
+ try {
249
+ const body = ctx.body;
250
+ console.log("Status Timeout:", body);
251
+ ctx.set.status = 200;
252
+ return {
253
+ ResultCode: 0,
254
+ ResultDesc: "Timeout received"
255
+ };
256
+ } catch (error) {
257
+ console.error("Status Timeout error:", error);
258
+ ctx.set.status = 200;
259
+ return {
260
+ ResultCode: 1,
261
+ ResultDesc: "Processing failed"
262
+ };
263
+ }
264
+ },
265
+ stkPush: async (ctx) => {
266
+ try {
267
+ const {
268
+ amount,
269
+ phoneNumber,
270
+ accountReference,
271
+ transactionDesc,
272
+ callbackUrl
273
+ } = ctx.body;
274
+ if (!amount || !phoneNumber) {
275
+ ctx.set.status = 400;
276
+ return { error: "Amount and phone number are required" };
277
+ }
278
+ const response = await client.stkPush({
279
+ amount: Number(amount),
280
+ phoneNumber: String(phoneNumber),
281
+ accountReference: accountReference || "Payment",
282
+ transactionDesc: transactionDesc || "Payment",
283
+ callbackUrl
284
+ });
285
+ return response;
286
+ } catch (error) {
287
+ console.error("STK Push error:", error);
288
+ ctx.set.status = 500;
289
+ return { error: error.message || "Request failed" };
290
+ }
291
+ },
292
+ stkQuery: async (ctx) => {
293
+ try {
294
+ const { CheckoutRequestID } = ctx.body;
295
+ if (!CheckoutRequestID) {
296
+ ctx.set.status = 400;
297
+ return { error: "CheckoutRequestID is required" };
298
+ }
299
+ const response = await client.stkQuery({ CheckoutRequestID });
300
+ return response;
301
+ } catch (error) {
302
+ console.error("STK Query error:", error);
303
+ ctx.set.status = 500;
304
+ return { error: error.message || "Request failed" };
305
+ }
306
+ },
307
+ b2c: async (ctx) => {
308
+ try {
309
+ const {
310
+ amount,
311
+ phoneNumber,
312
+ commandID,
313
+ remarks,
314
+ occasion,
315
+ resultUrl,
316
+ timeoutUrl
317
+ } = ctx.body;
318
+ if (!amount || !phoneNumber || !commandID) {
319
+ ctx.set.status = 400;
320
+ return {
321
+ error: "Amount, phone number, and command ID are required"
322
+ };
323
+ }
324
+ const response = await client.b2c({
325
+ amount: Number(amount),
326
+ phoneNumber: String(phoneNumber),
327
+ commandID,
328
+ remarks: remarks || "Payment",
329
+ occasion,
330
+ resultUrl,
331
+ timeoutUrl
332
+ });
333
+ return response;
334
+ } catch (error) {
335
+ console.error("B2C error:", error);
336
+ ctx.set.status = 500;
337
+ return { error: error.message || "Request failed" };
338
+ }
339
+ },
340
+ b2b: async (ctx) => {
341
+ try {
342
+ const {
343
+ amount,
344
+ partyB,
345
+ commandID,
346
+ senderIdentifierType,
347
+ receiverIdentifierType,
348
+ accountReference,
349
+ remarks,
350
+ resultUrl,
351
+ timeoutUrl
352
+ } = ctx.body;
353
+ console.log("B2B Request Parameters:", {
354
+ amount,
355
+ partyB,
356
+ commandID,
357
+ senderIdentifierType,
358
+ receiverIdentifierType,
359
+ accountReference,
360
+ remarks
361
+ });
362
+ if (!amount || !partyB || !commandID || !accountReference) {
363
+ ctx.set.status = 400;
364
+ return {
365
+ error: "Amount, partyB, commandID, and account reference are required"
366
+ };
367
+ }
368
+ const response = await client.b2b({
369
+ amount: Number(amount),
370
+ partyB: String(partyB),
371
+ commandID,
372
+ senderIdentifierType,
373
+ receiverIdentifierType,
374
+ accountReference: String(accountReference),
375
+ remarks: remarks || "Payment",
376
+ resultUrl,
377
+ timeoutUrl
378
+ });
379
+ console.log("B2B Response:", response);
380
+ return response;
381
+ } catch (error) {
382
+ console.error("B2B error:", error);
383
+ ctx.set.status = 500;
384
+ return { error: error.message || "Request failed" };
385
+ }
386
+ },
387
+ balance: async (ctx) => {
388
+ try {
389
+ const response = await client.accountBalance(
390
+ ctx.body
391
+ );
392
+ return response;
393
+ } catch (error) {
394
+ console.error("Balance error:", error);
395
+ ctx.set.status = 500;
396
+ return { error: error.message || "Request failed" };
397
+ }
398
+ },
399
+ transactionStatus: async (ctx) => {
400
+ try {
401
+ const { transactionID } = ctx.body;
402
+ if (!transactionID) {
403
+ ctx.set.status = 400;
404
+ return { error: "Transaction ID is required" };
405
+ }
406
+ const response = await client.transactionStatus(ctx.body);
407
+ return response;
408
+ } catch (error) {
409
+ console.error("Transaction Status error:", error);
410
+ ctx.set.status = 500;
411
+ return { error: error.message || "Request failed" };
412
+ }
413
+ },
414
+ reversal: async (ctx) => {
415
+ try {
416
+ const { transactionID, amount } = ctx.body;
417
+ if (!transactionID || !amount) {
418
+ ctx.set.status = 400;
419
+ return { error: "Transaction ID and amount are required" };
420
+ }
421
+ const response = await client.reversal(ctx.body);
422
+ return response;
423
+ } catch (error) {
424
+ console.error("Reversal error:", error);
425
+ ctx.set.status = 500;
426
+ return { error: error.message || "Request failed" };
427
+ }
428
+ },
429
+ registerC2B: async (ctx) => {
430
+ try {
431
+ const { shortCode, responseType, confirmationURL, validationURL } = ctx.body;
432
+ if (!confirmationURL || !validationURL) {
433
+ ctx.set.status = 400;
434
+ return {
435
+ error: "Confirmation URL and validation URL are required"
436
+ };
437
+ }
438
+ const response = await client.registerC2BUrl({
439
+ shortCode,
440
+ responseType,
441
+ confirmationURL,
442
+ validationURL
443
+ });
444
+ return response;
445
+ } catch (error) {
446
+ console.error("Register C2B error:", error);
447
+ ctx.set.status = 500;
448
+ return { error: error.message || "Request failed" };
449
+ }
450
+ },
451
+ generateQR: async (ctx) => {
452
+ try {
453
+ const {
454
+ merchantName,
455
+ refNo,
456
+ amount,
457
+ transactionType,
458
+ creditPartyIdentifier,
459
+ size
460
+ } = ctx.body;
461
+ if (!merchantName || !refNo || !amount || !transactionType || !creditPartyIdentifier) {
462
+ ctx.set.status = 400;
463
+ return {
464
+ error: "Merchant name, reference number, amount, transaction type, and credit party identifier are required",
465
+ received: ctx.body
466
+ };
467
+ }
468
+ let qrSize = void 0;
469
+ if (size) {
470
+ if (size !== "500" && size !== "300") {
471
+ ctx.set.status = 400;
472
+ return {
473
+ error: "Size must be either '300' or '500'"
474
+ };
475
+ }
476
+ qrSize = size;
477
+ }
478
+ const response = await client.generateDynamicQR({
479
+ merchantName,
480
+ refNo,
481
+ amount: Number(amount),
482
+ transactionType,
483
+ creditPartyIdentifier,
484
+ size: qrSize
485
+ });
486
+ return response;
487
+ } catch (error) {
488
+ console.error("Generate QR error:", error);
489
+ ctx.set.status = 500;
490
+ return { error: error.message || "Request failed" };
491
+ }
492
+ }
493
+ };
494
+ return handlers;
495
+ }
496
+
497
+ // src/index.ts
498
+ var import_core2 = require("@singularity-payments/core");
499
+ function createMpesa(config, options) {
500
+ const client = new import_core.MpesaClient(config, options);
501
+ const handlers = createMpesaHandlers(client);
502
+ const app = new import_elysia.Elysia({ prefix: "/mpesa" }).post("/stk-push", handlers.stkPush).post("/stk-query", handlers.stkQuery).post("/callback", handlers.stkCallback).post("/b2c", handlers.b2c).post("/b2b", handlers.b2b).post("/balance", handlers.balance).post("/transaction-status", handlers.transactionStatus).post("/reversal", handlers.reversal).post("/register-c2b", handlers.registerC2B).post("/generate-qr", handlers.generateQR).post("/c2b-validation", handlers.c2bValidation).post("/c2b-confirmation", handlers.c2bConfirmation).post("/b2c-result", handlers.b2cResult).post("/b2c-timeout", handlers.b2cTimeout).post("/b2b-result", handlers.b2bResult).post("/b2b-timeout", handlers.b2bTimeout).post("/balance-result", handlers.balanceResult).post("/balance-timeout", handlers.balanceTimeout).post("/reversal-result", handlers.reversalResult).post("/reversal-timeout", handlers.reversalTimeout).post("/status-result", handlers.statusResult).post("/status-timeout", handlers.statusTimeout);
503
+ return {
504
+ client,
505
+ handlers,
506
+ app
507
+ };
508
+ }
509
+ // Annotate the CommonJS export names for ESM import in node:
510
+ 0 && (module.exports = {
511
+ MpesaClient,
512
+ createMpesa,
513
+ createMpesaHandlers
514
+ });