@nile-squad/nylonpay-ts 1.0.4 → 1.0.5
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.cjs +284 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -10
- package/dist/index.d.ts +40 -10
- package/dist/index.js +285 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, createHmac, timingSafeEqual, randomBytes } from 'crypto';
|
|
2
|
-
import { Ok, Err } from 'slang-ts';
|
|
2
|
+
import { Ok, Err, safeTry } from 'slang-ts';
|
|
3
3
|
import { type, platform, arch, release, hostname } from 'os';
|
|
4
4
|
|
|
5
5
|
// src/sdk.ts
|
|
@@ -53,21 +53,6 @@ function createEmitter() {
|
|
|
53
53
|
const emitter = { on, once, off, emit, clear, listenerCount };
|
|
54
54
|
return emitter;
|
|
55
55
|
}
|
|
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");
|
|
67
|
-
}
|
|
68
|
-
function generateNonce(length = 16) {
|
|
69
|
-
return randomBytes(length).toString("hex");
|
|
70
|
-
}
|
|
71
56
|
|
|
72
57
|
// src/sdk.config.ts
|
|
73
58
|
var DEFAULT_BASE_URL = "https://api.nylonpay.nilesquad.com/api/services";
|
|
@@ -76,6 +61,9 @@ var DEFAULT_MAX_RETRIES = 3;
|
|
|
76
61
|
var DEFAULT_MAX_POLL_INTERVAL_MS = 2e3;
|
|
77
62
|
var DEFAULT_MAX_POLL_DURATION_MS = 3e5;
|
|
78
63
|
var DEFAULT_MAX_POLL_ATTEMPTS = 150;
|
|
64
|
+
var DEFAULT_STREAMING = true;
|
|
65
|
+
var STREAM_PATH = "/sse/transaction";
|
|
66
|
+
var MAX_STREAM_RECONNECTS = 2;
|
|
79
67
|
var SDK_SERVICE = "sdk";
|
|
80
68
|
var SDK_ACTIONS = {
|
|
81
69
|
collectPayment: "sdk-collect-payment",
|
|
@@ -88,6 +76,21 @@ var SDK_ACTIONS = {
|
|
|
88
76
|
createInvoice: "sdk-create-invoice"
|
|
89
77
|
};
|
|
90
78
|
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
|
|
79
|
+
function generateFingerprint() {
|
|
80
|
+
const components = [
|
|
81
|
+
`type:${type()}`,
|
|
82
|
+
`platform:${platform()}`,
|
|
83
|
+
`arch:${arch()}`,
|
|
84
|
+
`release:${release()}`,
|
|
85
|
+
`hostname:${hostname()}`,
|
|
86
|
+
`node:${process.versions.node}`,
|
|
87
|
+
`v8:${process.versions.v8}`
|
|
88
|
+
].join("|");
|
|
89
|
+
return createHash("sha256").update(components).digest("hex");
|
|
90
|
+
}
|
|
91
|
+
function generateNonce(length = 16) {
|
|
92
|
+
return randomBytes(length).toString("hex");
|
|
93
|
+
}
|
|
91
94
|
function sortValue(value) {
|
|
92
95
|
if (Array.isArray(value)) {
|
|
93
96
|
return value.map((entry) => sortValue(entry));
|
|
@@ -118,6 +121,42 @@ function createSignature(input) {
|
|
|
118
121
|
function createTimestamp() {
|
|
119
122
|
return Date.now().toString();
|
|
120
123
|
}
|
|
124
|
+
|
|
125
|
+
// src/sse-parse.ts
|
|
126
|
+
function parseBlock(block) {
|
|
127
|
+
let event = "message";
|
|
128
|
+
const dataLines = [];
|
|
129
|
+
for (const rawLine of block.split("\n")) {
|
|
130
|
+
const line = rawLine.replace(/\r$/, "");
|
|
131
|
+
if (line.startsWith(":")) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (line.startsWith("event:")) {
|
|
135
|
+
event = line.slice("event:".length).trim();
|
|
136
|
+
} else if (line.startsWith("data:")) {
|
|
137
|
+
dataLines.push(line.slice("data:".length).trim());
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (dataLines.length === 0) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return { event, data: dataLines.join("\n") };
|
|
144
|
+
}
|
|
145
|
+
function parseSseBuffer(buffer) {
|
|
146
|
+
const messages = [];
|
|
147
|
+
let rest = buffer;
|
|
148
|
+
let separator = rest.indexOf("\n\n");
|
|
149
|
+
while (separator !== -1) {
|
|
150
|
+
const block = rest.slice(0, separator);
|
|
151
|
+
rest = rest.slice(separator + 2);
|
|
152
|
+
const message = parseBlock(block);
|
|
153
|
+
if (message) {
|
|
154
|
+
messages.push(message);
|
|
155
|
+
}
|
|
156
|
+
separator = rest.indexOf("\n\n");
|
|
157
|
+
}
|
|
158
|
+
return { messages, rest };
|
|
159
|
+
}
|
|
121
160
|
function verifyResponseSignature(data, signature, secret) {
|
|
122
161
|
const expectedSignature = createHmac("sha256", secret).update(createCanonicalPayload(data)).digest("hex");
|
|
123
162
|
const providedBuffer = Buffer.from(signature, "hex");
|
|
@@ -130,6 +169,55 @@ function verifyResponseSignature(data, signature, secret) {
|
|
|
130
169
|
|
|
131
170
|
// src/transport.ts
|
|
132
171
|
var CACHED_FINGERPRINT = generateFingerprint();
|
|
172
|
+
function streamUrl(baseUrl) {
|
|
173
|
+
try {
|
|
174
|
+
return new URL(baseUrl).origin + STREAM_PATH;
|
|
175
|
+
} catch {
|
|
176
|
+
return baseUrl.replace(/\/api\/services\/?$/u, "") + STREAM_PATH;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
var KNOWN_CATEGORIES = /* @__PURE__ */ new Set([
|
|
180
|
+
"auth",
|
|
181
|
+
"validation",
|
|
182
|
+
"limit",
|
|
183
|
+
"rate_limit",
|
|
184
|
+
"account",
|
|
185
|
+
"provider",
|
|
186
|
+
"not_found",
|
|
187
|
+
"internal",
|
|
188
|
+
"network",
|
|
189
|
+
"timeout"
|
|
190
|
+
]);
|
|
191
|
+
var STATUS_CATEGORY = {
|
|
192
|
+
408: "timeout",
|
|
193
|
+
429: "rate_limit"
|
|
194
|
+
};
|
|
195
|
+
var ERROR_TYPE_SUFFIX = /^(.*?)\s*--\s*error-type:\s*([a-z_]+)\s*$/is;
|
|
196
|
+
function parseCategoryFromMessage(message) {
|
|
197
|
+
const match = ERROR_TYPE_SUFFIX.exec(message);
|
|
198
|
+
if (match?.[2] && KNOWN_CATEGORIES.has(match[2])) {
|
|
199
|
+
return {
|
|
200
|
+
category: match[2],
|
|
201
|
+
message: match[1] ?? message
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return { category: null, message };
|
|
205
|
+
}
|
|
206
|
+
function buildHttpError(params) {
|
|
207
|
+
const parsed = parseCategoryFromMessage(params.message);
|
|
208
|
+
const category = parsed.category ?? STATUS_CATEGORY[params.statusCode] ?? (params.statusCode >= 500 ? "internal" : "validation");
|
|
209
|
+
return {
|
|
210
|
+
category,
|
|
211
|
+
message: parsed.message,
|
|
212
|
+
retryable: RETRYABLE_STATUS_CODES.has(params.statusCode)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function createSdkError(error) {
|
|
216
|
+
return Object.assign(new Error(error.message), {
|
|
217
|
+
category: error.category,
|
|
218
|
+
retryable: error.retryable
|
|
219
|
+
});
|
|
220
|
+
}
|
|
133
221
|
function calculateBackoff(attempt) {
|
|
134
222
|
const base = 2 ** attempt * 1e3;
|
|
135
223
|
const jitter = Math.random() * 500;
|
|
@@ -232,21 +320,19 @@ function createTransport({
|
|
|
232
320
|
await delay(calculateBackoff(currentAttempt));
|
|
233
321
|
return attempt(currentAttempt + 1);
|
|
234
322
|
}
|
|
235
|
-
const sdkError = {
|
|
236
|
-
code: `HTTP_${statusCode}`,
|
|
237
|
-
message: errorMessage,
|
|
238
|
-
statusCode,
|
|
239
|
-
retryable
|
|
240
|
-
};
|
|
241
323
|
cleanup();
|
|
242
|
-
return Err(
|
|
324
|
+
return Err(
|
|
325
|
+
JSON.stringify(
|
|
326
|
+
buildHttpError({ message: errorMessage, statusCode })
|
|
327
|
+
)
|
|
328
|
+
);
|
|
243
329
|
}
|
|
244
330
|
const responseBody = await response.json();
|
|
245
331
|
if (!responseBody || typeof responseBody !== "object" || !("status" in responseBody)) {
|
|
246
332
|
cleanup();
|
|
247
333
|
return Err(
|
|
248
334
|
JSON.stringify({
|
|
249
|
-
|
|
335
|
+
category: "internal",
|
|
250
336
|
message: "Response missing status field",
|
|
251
337
|
retryable: false
|
|
252
338
|
})
|
|
@@ -265,7 +351,7 @@ function createTransport({
|
|
|
265
351
|
cleanup();
|
|
266
352
|
return Err(
|
|
267
353
|
JSON.stringify({
|
|
268
|
-
|
|
354
|
+
category: "internal",
|
|
269
355
|
message: "Response signature verification failed",
|
|
270
356
|
retryable: false
|
|
271
357
|
})
|
|
@@ -282,7 +368,7 @@ function createTransport({
|
|
|
282
368
|
cleanup();
|
|
283
369
|
const isAbort = error instanceof DOMException && error.name === "AbortError";
|
|
284
370
|
const sdkError = {
|
|
285
|
-
|
|
371
|
+
category: isAbort ? "timeout" : "network",
|
|
286
372
|
message: isAbort ? `Request timed out after ${timeoutMs}ms` : String(error),
|
|
287
373
|
retryable: true
|
|
288
374
|
};
|
|
@@ -295,17 +381,105 @@ function createTransport({
|
|
|
295
381
|
}
|
|
296
382
|
return attempt(0);
|
|
297
383
|
}
|
|
298
|
-
|
|
384
|
+
function openStream(input) {
|
|
385
|
+
const controller = new AbortController();
|
|
386
|
+
let closed = false;
|
|
387
|
+
const close = () => {
|
|
388
|
+
if (closed) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
closed = true;
|
|
392
|
+
controller.abort();
|
|
393
|
+
};
|
|
394
|
+
const payload = {
|
|
395
|
+
reference: input.reference,
|
|
396
|
+
_fingerprint: CACHED_FINGERPRINT
|
|
397
|
+
};
|
|
398
|
+
const headers = buildAuthHeaders({ apiKey, apiSecret, payload });
|
|
399
|
+
const url = streamUrl(baseUrl);
|
|
400
|
+
const run = async () => {
|
|
401
|
+
const fetchResult = await safeTry(
|
|
402
|
+
() => fetchImpl(url, {
|
|
403
|
+
method: "POST",
|
|
404
|
+
headers,
|
|
405
|
+
body: JSON.stringify(payload),
|
|
406
|
+
signal: controller.signal
|
|
407
|
+
})
|
|
408
|
+
);
|
|
409
|
+
if (fetchResult.isErr) {
|
|
410
|
+
if (!closed) {
|
|
411
|
+
input.onError(fetchResult.error);
|
|
412
|
+
}
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const response = fetchResult.value;
|
|
416
|
+
if (!response.ok || !response.body) {
|
|
417
|
+
const textResult = await safeTry(() => response.text());
|
|
418
|
+
const message = textResult.isOk ? textResult.value : `HTTP ${response.status}`;
|
|
419
|
+
if (!closed) {
|
|
420
|
+
input.onError(message || `HTTP ${response.status}`);
|
|
421
|
+
}
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const reader = response.body.getReader();
|
|
425
|
+
const decoder = new TextDecoder();
|
|
426
|
+
let buffer = "";
|
|
427
|
+
while (!closed) {
|
|
428
|
+
const chunkResult = await safeTry(() => reader.read());
|
|
429
|
+
if (chunkResult.isErr) {
|
|
430
|
+
if (!closed) {
|
|
431
|
+
input.onError(chunkResult.error);
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const chunk = chunkResult.value;
|
|
436
|
+
if (chunk.done) {
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
440
|
+
const { messages, rest } = parseSseBuffer(buffer);
|
|
441
|
+
buffer = rest;
|
|
442
|
+
for (const message of messages) {
|
|
443
|
+
if (message.event === "status") {
|
|
444
|
+
const statusResult = await safeTry(
|
|
445
|
+
() => JSON.parse(message.data)
|
|
446
|
+
);
|
|
447
|
+
if (statusResult.isOk) {
|
|
448
|
+
input.onStatus(statusResult.value);
|
|
449
|
+
}
|
|
450
|
+
} else if (message.event === "error") {
|
|
451
|
+
const errDataResult = await safeTry(
|
|
452
|
+
() => JSON.parse(message.data)
|
|
453
|
+
);
|
|
454
|
+
const text = errDataResult.isOk ? errDataResult.value.message ?? message.data : message.data;
|
|
455
|
+
close();
|
|
456
|
+
input.onError(text);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (!closed) {
|
|
462
|
+
input.onClose();
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
void run();
|
|
466
|
+
return { close };
|
|
467
|
+
}
|
|
468
|
+
return { send, openStream, parseError };
|
|
299
469
|
}
|
|
300
470
|
function parseError(error) {
|
|
301
471
|
try {
|
|
302
472
|
const parsed = JSON.parse(error);
|
|
303
|
-
if (parsed && typeof parsed === "object" && "
|
|
473
|
+
if (parsed && typeof parsed === "object" && "category" in parsed && "message" in parsed && typeof parsed.category === "string" && typeof parsed.message === "string") {
|
|
304
474
|
return parsed;
|
|
305
475
|
}
|
|
306
476
|
} catch {
|
|
307
477
|
}
|
|
308
|
-
|
|
478
|
+
const fromSuffix = parseCategoryFromMessage(error);
|
|
479
|
+
return {
|
|
480
|
+
category: fromSuffix.category ?? "internal",
|
|
481
|
+
message: fromSuffix.message
|
|
482
|
+
};
|
|
309
483
|
}
|
|
310
484
|
|
|
311
485
|
// src/payment.ts
|
|
@@ -341,11 +515,15 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
341
515
|
fetchTransaction: deps.fetchTransaction,
|
|
342
516
|
pollIntervalMs: deps.pollIntervalMs ?? 2e3,
|
|
343
517
|
maxPollDuration: deps.maxPollDuration ?? 3e5,
|
|
344
|
-
maxPollAttempts: deps.maxPollAttempts ?? 150
|
|
518
|
+
maxPollAttempts: deps.maxPollAttempts ?? 150,
|
|
519
|
+
streaming: deps.streaming ?? false,
|
|
520
|
+
openStream: deps.openStream,
|
|
521
|
+
streamHandle: null,
|
|
522
|
+
streamReconnects: 0
|
|
345
523
|
};
|
|
346
524
|
function resolveWithError(error) {
|
|
347
525
|
state.resolved = true;
|
|
348
|
-
|
|
526
|
+
stopUpdates();
|
|
349
527
|
emitEvent("error", parseError(error).message);
|
|
350
528
|
}
|
|
351
529
|
function emitEvent(event, error) {
|
|
@@ -372,7 +550,7 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
372
550
|
emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
|
|
373
551
|
}
|
|
374
552
|
state.resolved = true;
|
|
375
|
-
|
|
553
|
+
stopUpdates();
|
|
376
554
|
}
|
|
377
555
|
async function handleStatusUpdate(response) {
|
|
378
556
|
if (response.reference !== state.reference) {
|
|
@@ -396,13 +574,13 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
396
574
|
}
|
|
397
575
|
}
|
|
398
576
|
function handlePollError(error) {
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
577
|
+
const parsed = parseError(error);
|
|
578
|
+
if (parsed.category === "not_found") {
|
|
401
579
|
return;
|
|
402
580
|
}
|
|
403
|
-
emitEvent("error",
|
|
581
|
+
emitEvent("error", parsed.message);
|
|
404
582
|
state.resolved = true;
|
|
405
|
-
|
|
583
|
+
stopUpdates();
|
|
406
584
|
}
|
|
407
585
|
function scheduleNextPoll() {
|
|
408
586
|
if (state.resolved || state.pollingTimer) {
|
|
@@ -415,7 +593,7 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
415
593
|
}
|
|
416
594
|
async function pollStatus() {
|
|
417
595
|
if (state.resolved) {
|
|
418
|
-
|
|
596
|
+
stopUpdates();
|
|
419
597
|
return;
|
|
420
598
|
}
|
|
421
599
|
if (state.pollAttempts >= state.maxPollAttempts) {
|
|
@@ -434,25 +612,66 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
434
612
|
handlePollError(result.error);
|
|
435
613
|
}
|
|
436
614
|
if (state.resolved) {
|
|
437
|
-
|
|
615
|
+
stopUpdates();
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
scheduleNextPoll();
|
|
619
|
+
}
|
|
620
|
+
function closeStream() {
|
|
621
|
+
if (state.streamHandle) {
|
|
622
|
+
state.streamHandle.close();
|
|
623
|
+
state.streamHandle = null;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function startStream() {
|
|
627
|
+
if (state.resolved || !state.openStream) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
state.streamHandle = state.openStream({
|
|
631
|
+
reference: state.reference,
|
|
632
|
+
onStatus: (status) => {
|
|
633
|
+
void handleStatusUpdate(status);
|
|
634
|
+
},
|
|
635
|
+
onError: () => handleStreamFailure(),
|
|
636
|
+
onClose: () => handleStreamFailure()
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
function handleStreamFailure() {
|
|
640
|
+
closeStream();
|
|
641
|
+
if (state.resolved) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
if (state.streamReconnects < MAX_STREAM_RECONNECTS) {
|
|
645
|
+
state.streamReconnects += 1;
|
|
646
|
+
const backoff = 500 * 2 ** (state.streamReconnects - 1) + Math.random() * 250;
|
|
647
|
+
setTimeout(() => {
|
|
648
|
+
if (!state.resolved) {
|
|
649
|
+
startStream();
|
|
650
|
+
}
|
|
651
|
+
}, backoff);
|
|
438
652
|
return;
|
|
439
653
|
}
|
|
440
654
|
scheduleNextPoll();
|
|
441
655
|
}
|
|
442
|
-
function
|
|
443
|
-
if (TERMINAL_STATES.has(state.status
|
|
656
|
+
function startUpdates() {
|
|
657
|
+
if (TERMINAL_STATES.has(state.status)) {
|
|
444
658
|
setTimeout(() => {
|
|
445
659
|
void handleTerminalState(state.status);
|
|
446
660
|
}, 0);
|
|
447
661
|
return;
|
|
448
662
|
}
|
|
663
|
+
if (state.streaming && state.openStream) {
|
|
664
|
+
startStream();
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
449
667
|
scheduleNextPoll();
|
|
450
668
|
}
|
|
451
|
-
function
|
|
669
|
+
function stopUpdates() {
|
|
452
670
|
if (state.pollingTimer) {
|
|
453
671
|
clearTimeout(state.pollingTimer);
|
|
454
672
|
state.pollingTimer = null;
|
|
455
673
|
}
|
|
674
|
+
closeStream();
|
|
456
675
|
}
|
|
457
676
|
function on(event, handler) {
|
|
458
677
|
state.emitter.on(event, handler);
|
|
@@ -514,7 +733,7 @@ function createPaymentInstance(initialResponse, deps) {
|
|
|
514
733
|
off,
|
|
515
734
|
wait
|
|
516
735
|
};
|
|
517
|
-
|
|
736
|
+
startUpdates();
|
|
518
737
|
return paymentInstance;
|
|
519
738
|
}
|
|
520
739
|
function verifyWebhookSignature(input) {
|
|
@@ -532,14 +751,17 @@ function verifyWebhookSignature(input) {
|
|
|
532
751
|
function generateReference() {
|
|
533
752
|
return randomBytes(16).toString("hex").slice(0, 15);
|
|
534
753
|
}
|
|
754
|
+
function throwValidation(message) {
|
|
755
|
+
throw createSdkError({ category: "validation", message });
|
|
756
|
+
}
|
|
535
757
|
function validateAmount(amount) {
|
|
536
758
|
if (!Number.isInteger(amount) || amount <= 0) {
|
|
537
|
-
|
|
759
|
+
throwValidation("amount must be a positive integer");
|
|
538
760
|
}
|
|
539
761
|
}
|
|
540
762
|
function validateNonEmpty(value, fieldName) {
|
|
541
763
|
if (!value || value.trim() === "") {
|
|
542
|
-
|
|
764
|
+
throwValidation(`${fieldName} is required`);
|
|
543
765
|
}
|
|
544
766
|
}
|
|
545
767
|
function createSdkInstance(config) {
|
|
@@ -562,7 +784,9 @@ function createSdkInstance(config) {
|
|
|
562
784
|
}),
|
|
563
785
|
pollIntervalMs: config.maxPollIntervalMs,
|
|
564
786
|
maxPollDuration: config.maxPollDurationMs,
|
|
565
|
-
maxPollAttempts: config.maxPollAttempts
|
|
787
|
+
maxPollAttempts: config.maxPollAttempts,
|
|
788
|
+
streaming: config.streaming,
|
|
789
|
+
openStream: config.streaming ? transport.openStream : void 0
|
|
566
790
|
};
|
|
567
791
|
async function collectPayment(input) {
|
|
568
792
|
const reference = input.reference ?? generateReference();
|
|
@@ -571,7 +795,7 @@ function createSdkInstance(config) {
|
|
|
571
795
|
validateNonEmpty(input.customer.phoneNumber, "customer.phoneNumber");
|
|
572
796
|
validateNonEmpty(input.description, "description");
|
|
573
797
|
if (input.method === "bank" && !input.bank) {
|
|
574
|
-
|
|
798
|
+
throwValidation('bank details are required when method is "bank"');
|
|
575
799
|
}
|
|
576
800
|
let payload = { ...input, reference };
|
|
577
801
|
if (config.hooks?.beforeCollect) {
|
|
@@ -592,19 +816,10 @@ function createSdkInstance(config) {
|
|
|
592
816
|
payload
|
|
593
817
|
);
|
|
594
818
|
}
|
|
595
|
-
if (result.
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
return createPaymentInstance(
|
|
599
|
-
{ reference, status: "pending" },
|
|
600
|
-
{
|
|
601
|
-
fetchStatus: async () => Err(result.error),
|
|
602
|
-
fetchTransaction: async () => Err(result.error),
|
|
603
|
-
pollIntervalMs: 0,
|
|
604
|
-
maxPollAttempts: 1,
|
|
605
|
-
maxPollDuration: Number.MAX_SAFE_INTEGER
|
|
606
|
-
}
|
|
607
|
-
);
|
|
819
|
+
if (result.isErr) {
|
|
820
|
+
throw createSdkError(parseError(result.error));
|
|
821
|
+
}
|
|
822
|
+
return createPaymentInstance(result.value, commonDeps);
|
|
608
823
|
}
|
|
609
824
|
async function collectPaymentAndResolve(input) {
|
|
610
825
|
const reference = input.reference ?? generateReference();
|
|
@@ -613,7 +828,7 @@ function createSdkInstance(config) {
|
|
|
613
828
|
validateNonEmpty(input.customer.phoneNumber, "customer.phoneNumber");
|
|
614
829
|
validateNonEmpty(input.description, "description");
|
|
615
830
|
if (input.method === "bank" && !input.bank) {
|
|
616
|
-
|
|
831
|
+
throwValidation('bank details are required when method is "bank"');
|
|
617
832
|
}
|
|
618
833
|
let payload = { ...input, reference };
|
|
619
834
|
if (config.hooks?.beforeCollect) {
|
|
@@ -672,19 +887,10 @@ function createSdkInstance(config) {
|
|
|
672
887
|
payload
|
|
673
888
|
);
|
|
674
889
|
}
|
|
675
|
-
if (result.
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
return createPaymentInstance(
|
|
679
|
-
{ reference, status: "pending" },
|
|
680
|
-
{
|
|
681
|
-
fetchStatus: async () => Err(result.error),
|
|
682
|
-
fetchTransaction: async () => Err(result.error),
|
|
683
|
-
pollIntervalMs: 0,
|
|
684
|
-
maxPollAttempts: 1,
|
|
685
|
-
maxPollDuration: Number.MAX_SAFE_INTEGER
|
|
686
|
-
}
|
|
687
|
-
);
|
|
890
|
+
if (result.isErr) {
|
|
891
|
+
throw createSdkError(parseError(result.error));
|
|
892
|
+
}
|
|
893
|
+
return createPaymentInstance(result.value, commonDeps);
|
|
688
894
|
}
|
|
689
895
|
async function makePayoutAndResolve(input) {
|
|
690
896
|
const reference = input.reference ?? generateReference();
|
|
@@ -737,7 +943,7 @@ function createSdkInstance(config) {
|
|
|
737
943
|
}
|
|
738
944
|
async function getTransaction(input) {
|
|
739
945
|
if (!input.id && !input.reference) {
|
|
740
|
-
|
|
946
|
+
throwValidation("id or reference is required");
|
|
741
947
|
}
|
|
742
948
|
const result = await transport.send({
|
|
743
949
|
action: SDK_ACTIONS.getTransaction,
|
|
@@ -765,14 +971,14 @@ function createSdkInstance(config) {
|
|
|
765
971
|
validateNonEmpty(input.description, "description");
|
|
766
972
|
if (input.items) {
|
|
767
973
|
if (input.items.length > 50) {
|
|
768
|
-
|
|
974
|
+
throwValidation("items must not exceed 50");
|
|
769
975
|
}
|
|
770
976
|
for (const item of input.items) {
|
|
771
977
|
if (!Number.isInteger(item.quantity) || item.quantity <= 0) {
|
|
772
|
-
|
|
978
|
+
throwValidation("item quantity must be a positive integer");
|
|
773
979
|
}
|
|
774
980
|
if (!Number.isInteger(item.unitPrice) || item.unitPrice <= 0) {
|
|
775
|
-
|
|
981
|
+
throwValidation("item unitPrice must be a positive integer");
|
|
776
982
|
}
|
|
777
983
|
}
|
|
778
984
|
}
|
|
@@ -832,6 +1038,7 @@ function createNylonPay(config) {
|
|
|
832
1038
|
maxPollIntervalMs: config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,
|
|
833
1039
|
maxPollDurationMs: config.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS,
|
|
834
1040
|
maxPollAttempts: config.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS,
|
|
1041
|
+
streaming: config.streaming ?? DEFAULT_STREAMING,
|
|
835
1042
|
fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
836
1043
|
hooks: config.hooks
|
|
837
1044
|
};
|
|
@@ -840,6 +1047,6 @@ function createNylonPay(config) {
|
|
|
840
1047
|
return instance;
|
|
841
1048
|
}
|
|
842
1049
|
|
|
843
|
-
export { createNylonPay, parseError, verifyWebhookSignature };
|
|
1050
|
+
export { createNylonPay, createSdkError, parseError, verifyWebhookSignature };
|
|
844
1051
|
//# sourceMappingURL=index.js.map
|
|
845
1052
|
//# sourceMappingURL=index.js.map
|