@nile-squad/nylonpay-ts 1.0.0 → 1.0.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 CHANGED
@@ -13,7 +13,7 @@ function createEmitter() {
13
13
  if (!state.listeners.has(event)) {
14
14
  state.listeners.set(event, /* @__PURE__ */ new Set());
15
15
  }
16
- state.listeners.get(event).add(handler);
16
+ state.listeners.get(event)?.add(handler);
17
17
  return () => off(event, handler);
18
18
  }
19
19
  function once(event, handler) {
@@ -53,217 +53,24 @@ function createEmitter() {
53
53
  const emitter = { on, once, off, emit, clear, listenerCount };
54
54
  return emitter;
55
55
  }
56
-
57
- // src/payment.ts
58
- var STATUS_TO_EVENT = {
59
- successful: "success",
60
- failed: "failed",
61
- processing: "processing",
62
- cancelled: "cancelled"
63
- };
64
- function statusToEvent(status) {
65
- return STATUS_TO_EVENT[status] ?? null;
56
+ function generateFingerprint() {
57
+ const components = [
58
+ `type:${type()}`,
59
+ `platform:${platform()}`,
60
+ `arch:${arch()}`,
61
+ `release:${release()}`,
62
+ `hostname:${hostname()}`,
63
+ `node:${process.versions.node}`,
64
+ `v8:${process.versions.v8}`
65
+ ].join("|");
66
+ return createHash("sha256").update(components).digest("hex");
66
67
  }
67
- var TERMINAL_STATES = /* @__PURE__ */ new Set([
68
- "successful",
69
- "failed",
70
- "cancelled"
71
- ]);
72
- function createPaymentInstance(initialResponse, deps) {
73
- const state = {
74
- reference: initialResponse.reference,
75
- status: initialResponse.status,
76
- transaction: null,
77
- pollingTimer: null,
78
- resolved: false,
79
- pollAttempts: 0,
80
- pollStartTime: Date.now(),
81
- emitter: createEmitter(),
82
- fetchStatus: deps.fetchStatus,
83
- fetchTransaction: deps.fetchTransaction,
84
- pollIntervalMs: deps.pollIntervalMs ?? 2e3,
85
- maxPollDuration: deps.maxPollDuration ?? 3e5,
86
- maxPollAttempts: deps.maxPollAttempts ?? 150
87
- };
88
- function resolveWithError(error) {
89
- state.resolved = true;
90
- stopPolling();
91
- emitEvent("error", error);
92
- }
93
- function emitEvent(event, error) {
94
- const data = {
95
- event,
96
- transaction: state.transaction ?? void 0,
97
- error,
98
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
99
- };
100
- state.emitter.emit(event, data);
101
- }
102
- async function handleTerminalState(status) {
103
- const txResult = await state.fetchTransaction({
104
- reference: state.reference
105
- });
106
- if (txResult.isOk) {
107
- state.transaction = txResult.value;
108
- const event = statusToEvent(status);
109
- if (event) {
110
- emitEvent(event);
111
- }
112
- } else {
113
- emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
114
- }
115
- state.resolved = true;
116
- stopPolling();
117
- }
118
- async function handleStatusUpdate(response) {
119
- if (response.reference !== state.reference) {
120
- resolveWithError(
121
- `Reference mismatch: expected ${state.reference} but got ${response.reference}`
122
- );
123
- return;
124
- }
125
- const newStatus = response.status;
126
- const oldStatus = state.status;
127
- state.status = newStatus;
128
- if (newStatus !== oldStatus) {
129
- const event = statusToEvent(newStatus);
130
- if (event) {
131
- if (TERMINAL_STATES.has(newStatus)) {
132
- await handleTerminalState(newStatus);
133
- return;
134
- }
135
- emitEvent(event);
136
- }
137
- }
138
- }
139
- function handlePollError(error) {
140
- const isNotFound = error.includes("not found") || error.includes("NOT_FOUND");
141
- if (isNotFound) {
142
- return;
143
- }
144
- emitEvent("error", error);
145
- state.resolved = true;
146
- stopPolling();
147
- }
148
- function scheduleNextPoll() {
149
- if (state.resolved || state.pollingTimer) {
150
- return;
151
- }
152
- state.pollingTimer = setTimeout(() => {
153
- state.pollingTimer = null;
154
- void pollStatus();
155
- }, state.pollIntervalMs);
156
- }
157
- async function pollStatus() {
158
- if (state.resolved) {
159
- stopPolling();
160
- return;
161
- }
162
- if (state.pollAttempts >= state.maxPollAttempts) {
163
- resolveWithError("Polling timeout: exceeded maximum attempts");
164
- return;
165
- }
166
- if (Date.now() - state.pollStartTime >= state.maxPollDuration) {
167
- resolveWithError("Polling timeout: exceeded maximum duration");
168
- return;
169
- }
170
- state.pollAttempts += 1;
171
- const result = await state.fetchStatus({ reference: state.reference });
172
- if (result.isOk) {
173
- await handleStatusUpdate(result.value);
174
- } else {
175
- handlePollError(result.error);
176
- }
177
- if (state.resolved) {
178
- stopPolling();
179
- return;
180
- }
181
- scheduleNextPoll();
182
- }
183
- function startPolling() {
184
- scheduleNextPoll();
185
- }
186
- function stopPolling() {
187
- if (state.pollingTimer) {
188
- clearTimeout(state.pollingTimer);
189
- state.pollingTimer = null;
190
- }
191
- }
192
- function on(event, handler) {
193
- state.emitter.on(event, handler);
194
- return paymentInstance;
195
- }
196
- function off(event, handler) {
197
- state.emitter.off(event, handler);
198
- return paymentInstance;
199
- }
200
- function once(event, handler) {
201
- state.emitter.once(event, handler);
202
- return paymentInstance;
203
- }
204
- function wait() {
205
- return new Promise((resolve, reject) => {
206
- if (state.resolved) {
207
- if (state.status === "successful" && state.transaction) {
208
- resolve(state.transaction);
209
- } else {
210
- reject(new Error(`Payment ${state.status ?? "error"}`));
211
- }
212
- return;
213
- }
214
- function onSuccess() {
215
- cleanup();
216
- if (state.transaction) {
217
- resolve(state.transaction);
218
- } else {
219
- reject(
220
- new Error("Payment successful but transaction data unavailable")
221
- );
222
- }
223
- }
224
- function onFailed() {
225
- cleanup();
226
- reject(new Error("Payment failed"));
227
- }
228
- function onCancelled() {
229
- cleanup();
230
- reject(new Error("Payment cancelled"));
231
- }
232
- function onError(data) {
233
- cleanup();
234
- const eventData = data;
235
- reject(new Error(eventData.error ?? "Payment error"));
236
- }
237
- function cleanup() {
238
- state.emitter.off("success", onSuccess);
239
- state.emitter.off("failed", onFailed);
240
- state.emitter.off("cancelled", onCancelled);
241
- state.emitter.off("error", onError);
242
- }
243
- state.emitter.on("success", onSuccess);
244
- state.emitter.on("failed", onFailed);
245
- state.emitter.on("cancelled", onCancelled);
246
- state.emitter.on("error", onError);
247
- });
248
- }
249
- const paymentInstance = {
250
- get reference() {
251
- return state.reference;
252
- },
253
- get status() {
254
- return state.status;
255
- },
256
- on,
257
- once,
258
- off,
259
- wait
260
- };
261
- startPolling();
262
- return paymentInstance;
68
+ function generateNonce(length = 16) {
69
+ return randomBytes(length).toString("hex");
263
70
  }
264
71
 
265
72
  // src/sdk.config.ts
266
- var DEFAULT_BASE_URL = "https://api.nylonpay.io/api/services";
73
+ var DEFAULT_BASE_URL = "https://api.nylonpay.nilesquad.com/api/services";
267
74
  var DEFAULT_TIMEOUT_MS = 3e4;
268
75
  var DEFAULT_MAX_RETRIES = 3;
269
76
  var DEFAULT_MAX_POLL_INTERVAL_MS = 2e3;
@@ -281,21 +88,6 @@ var SDK_ACTIONS = {
281
88
  createInvoice: "sdk-create-invoice"
282
89
  };
283
90
  var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
284
- function generateFingerprint() {
285
- const components = [
286
- `type:${type()}`,
287
- `platform:${platform()}`,
288
- `arch:${arch()}`,
289
- `release:${release()}`,
290
- `hostname:${hostname()}`,
291
- `node:${process.versions.node}`,
292
- `v8:${process.versions.v8}`
293
- ].join("|");
294
- return createHash("sha256").update(components).digest("hex");
295
- }
296
- function generateNonce(length = 16) {
297
- return randomBytes(length).toString("hex");
298
- }
299
91
  function sortValue(value) {
300
92
  if (Array.isArray(value)) {
301
93
  return value.map((entry) => sortValue(entry));
@@ -515,6 +307,214 @@ function parseError(error) {
515
307
  }
516
308
  return { code: "UNKNOWN", message: error };
517
309
  }
310
+
311
+ // src/payment.ts
312
+ var STATUS_TO_EVENT = {
313
+ successful: "success",
314
+ failed: "failed",
315
+ processing: "processing",
316
+ cancelled: "cancelled"
317
+ };
318
+ function statusToEvent(status) {
319
+ return STATUS_TO_EVENT[status] ?? null;
320
+ }
321
+ var TERMINAL_STATES = /* @__PURE__ */ new Set([
322
+ "successful",
323
+ "failed",
324
+ "cancelled"
325
+ ]);
326
+ function createPaymentInstance(initialResponse, deps) {
327
+ const state = {
328
+ reference: initialResponse.reference,
329
+ status: initialResponse.status,
330
+ transaction: null,
331
+ pollingTimer: null,
332
+ resolved: false,
333
+ pollAttempts: 0,
334
+ pollStartTime: Date.now(),
335
+ emitter: createEmitter(),
336
+ fetchStatus: deps.fetchStatus,
337
+ fetchTransaction: deps.fetchTransaction,
338
+ pollIntervalMs: deps.pollIntervalMs ?? 2e3,
339
+ maxPollDuration: deps.maxPollDuration ?? 3e5,
340
+ maxPollAttempts: deps.maxPollAttempts ?? 150
341
+ };
342
+ function resolveWithError(error) {
343
+ state.resolved = true;
344
+ stopPolling();
345
+ emitEvent("error", parseError(error).message);
346
+ }
347
+ function emitEvent(event, error) {
348
+ const data = {
349
+ event,
350
+ transaction: state.transaction ?? void 0,
351
+ error,
352
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
353
+ };
354
+ state.emitter.emit(event, data);
355
+ }
356
+ async function handleTerminalState(status) {
357
+ const txResult = await state.fetchTransaction({
358
+ reference: state.reference
359
+ });
360
+ if (txResult.isOk) {
361
+ state.transaction = txResult.value;
362
+ const event = statusToEvent(status);
363
+ if (event) {
364
+ emitEvent(event);
365
+ }
366
+ } else {
367
+ emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
368
+ }
369
+ state.resolved = true;
370
+ stopPolling();
371
+ }
372
+ async function handleStatusUpdate(response) {
373
+ if (response.reference !== state.reference) {
374
+ resolveWithError(
375
+ `Reference mismatch: expected ${state.reference} but got ${response.reference}`
376
+ );
377
+ return;
378
+ }
379
+ const newStatus = response.status;
380
+ const oldStatus = state.status;
381
+ state.status = newStatus;
382
+ if (newStatus !== oldStatus) {
383
+ const event = statusToEvent(newStatus);
384
+ if (event) {
385
+ if (TERMINAL_STATES.has(newStatus)) {
386
+ await handleTerminalState(newStatus);
387
+ return;
388
+ }
389
+ emitEvent(event);
390
+ }
391
+ }
392
+ }
393
+ function handlePollError(error) {
394
+ const isNotFound = error.includes("not found") || error.includes("NOT_FOUND");
395
+ if (isNotFound) {
396
+ return;
397
+ }
398
+ emitEvent("error", parseError(error).message);
399
+ state.resolved = true;
400
+ stopPolling();
401
+ }
402
+ function scheduleNextPoll() {
403
+ if (state.resolved || state.pollingTimer) {
404
+ return;
405
+ }
406
+ state.pollingTimer = setTimeout(() => {
407
+ state.pollingTimer = null;
408
+ void pollStatus();
409
+ }, state.pollIntervalMs);
410
+ }
411
+ async function pollStatus() {
412
+ if (state.resolved) {
413
+ stopPolling();
414
+ return;
415
+ }
416
+ if (state.pollAttempts >= state.maxPollAttempts) {
417
+ resolveWithError("Polling timeout: exceeded maximum attempts");
418
+ return;
419
+ }
420
+ if (Date.now() - state.pollStartTime >= state.maxPollDuration) {
421
+ resolveWithError("Polling timeout: exceeded maximum duration");
422
+ return;
423
+ }
424
+ state.pollAttempts += 1;
425
+ const result = await state.fetchStatus({ reference: state.reference });
426
+ if (result.isOk) {
427
+ await handleStatusUpdate(result.value);
428
+ } else {
429
+ handlePollError(result.error);
430
+ }
431
+ if (state.resolved) {
432
+ stopPolling();
433
+ return;
434
+ }
435
+ scheduleNextPoll();
436
+ }
437
+ function startPolling() {
438
+ scheduleNextPoll();
439
+ }
440
+ function stopPolling() {
441
+ if (state.pollingTimer) {
442
+ clearTimeout(state.pollingTimer);
443
+ state.pollingTimer = null;
444
+ }
445
+ }
446
+ function on(event, handler) {
447
+ state.emitter.on(event, handler);
448
+ return paymentInstance;
449
+ }
450
+ function off(event, handler) {
451
+ state.emitter.off(event, handler);
452
+ return paymentInstance;
453
+ }
454
+ function once(event, handler) {
455
+ state.emitter.once(event, handler);
456
+ return paymentInstance;
457
+ }
458
+ function wait() {
459
+ return new Promise((resolve, reject) => {
460
+ if (state.resolved) {
461
+ if (state.status === "successful" && state.transaction) {
462
+ resolve(state.transaction);
463
+ } else {
464
+ reject(new Error(`Payment ${state.status ?? "error"}`));
465
+ }
466
+ return;
467
+ }
468
+ function onSuccess() {
469
+ cleanup();
470
+ if (state.transaction) {
471
+ resolve(state.transaction);
472
+ } else {
473
+ reject(
474
+ new Error("Payment successful but transaction data unavailable")
475
+ );
476
+ }
477
+ }
478
+ function onFailed() {
479
+ cleanup();
480
+ reject(new Error("Payment failed"));
481
+ }
482
+ function onCancelled() {
483
+ cleanup();
484
+ reject(new Error("Payment cancelled"));
485
+ }
486
+ function onError(data) {
487
+ cleanup();
488
+ const eventData = data;
489
+ reject(new Error(eventData.error ?? "Payment error"));
490
+ }
491
+ function cleanup() {
492
+ state.emitter.off("success", onSuccess);
493
+ state.emitter.off("failed", onFailed);
494
+ state.emitter.off("cancelled", onCancelled);
495
+ state.emitter.off("error", onError);
496
+ }
497
+ state.emitter.on("success", onSuccess);
498
+ state.emitter.on("failed", onFailed);
499
+ state.emitter.on("cancelled", onCancelled);
500
+ state.emitter.on("error", onError);
501
+ });
502
+ }
503
+ const paymentInstance = {
504
+ get reference() {
505
+ return state.reference;
506
+ },
507
+ get status() {
508
+ return state.status;
509
+ },
510
+ on,
511
+ once,
512
+ off,
513
+ wait
514
+ };
515
+ startPolling();
516
+ return paymentInstance;
517
+ }
518
518
  function verifyWebhookSignature(input) {
519
519
  const payloadBytes = typeof input.payload === "string" ? Buffer.from(input.payload, "utf8") : Buffer.from(input.payload);
520
520
  const expectedSignature = createHmac("sha256", input.secret).update(payloadBytes).digest("hex");