@delopay/sdk 0.165.0 → 0.167.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/README.md +2 -0
- package/dist/{chunk-CP5M5WR6.js → chunk-RWCROWXW.js} +491 -44
- package/dist/chunk-RWCROWXW.js.map +1 -0
- package/dist/index.cjs +489 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +283 -44
- package/dist/index.d.ts +283 -44
- package/dist/index.js +1 -1
- package/dist/internal.cjs +511 -54
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +77 -7
- package/dist/internal.d.ts +77 -7
- package/dist/internal.js +24 -12
- package/dist/internal.js.map +1 -1
- package/package.json +18 -17
- package/dist/chunk-CP5M5WR6.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1179,6 +1179,289 @@ var Customers = class {
|
|
|
1179
1179
|
}
|
|
1180
1180
|
};
|
|
1181
1181
|
|
|
1182
|
+
// src/recordCounter.ts
|
|
1183
|
+
var LF = 10;
|
|
1184
|
+
var CR = 13;
|
|
1185
|
+
var QUOTE = 34;
|
|
1186
|
+
var BACKSLASH = 92;
|
|
1187
|
+
var OPEN_BRACE = 123;
|
|
1188
|
+
var CLOSE_BRACE = 125;
|
|
1189
|
+
var OPEN_BRACKET = 91;
|
|
1190
|
+
var CLOSE_BRACKET = 93;
|
|
1191
|
+
var CsvRecordCounter = class {
|
|
1192
|
+
constructor() {
|
|
1193
|
+
this.inQuotes = false;
|
|
1194
|
+
this.newlines = 0;
|
|
1195
|
+
/** Whether anything but a line break has arrived since the last newline. */
|
|
1196
|
+
this.lineHasContent = false;
|
|
1197
|
+
}
|
|
1198
|
+
push(chunk) {
|
|
1199
|
+
let inQuotes = this.inQuotes;
|
|
1200
|
+
let newlines = this.newlines;
|
|
1201
|
+
let lineHasContent = this.lineHasContent;
|
|
1202
|
+
for (const byte of chunk) {
|
|
1203
|
+
if (byte === QUOTE) {
|
|
1204
|
+
inQuotes = !inQuotes;
|
|
1205
|
+
lineHasContent = true;
|
|
1206
|
+
} else if (inQuotes) {
|
|
1207
|
+
lineHasContent = true;
|
|
1208
|
+
} else if (byte === LF) {
|
|
1209
|
+
newlines++;
|
|
1210
|
+
lineHasContent = false;
|
|
1211
|
+
} else if (byte !== CR) {
|
|
1212
|
+
lineHasContent = true;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
this.inQuotes = inQuotes;
|
|
1216
|
+
this.newlines = newlines;
|
|
1217
|
+
this.lineHasContent = lineHasContent;
|
|
1218
|
+
}
|
|
1219
|
+
get records() {
|
|
1220
|
+
return Math.max(0, this.newlines - 1);
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* The export writer ends every line — the header and each record — with a
|
|
1224
|
+
* newline, so a whole body ends on one, outside quotes. RFC 4180 lets a
|
|
1225
|
+
* final line break be omitted, but these bodies never omit it, and without
|
|
1226
|
+
* that rule a file cut part-way through its last unquoted field
|
|
1227
|
+
* (`pay_1,12` of `pay_1,123`) would count as one more whole record and
|
|
1228
|
+
* match the figure it was announced with.
|
|
1229
|
+
*/
|
|
1230
|
+
get complete() {
|
|
1231
|
+
return this.newlines >= 1 && !this.inQuotes && !this.lineHasContent;
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* The records that ended. An unterminated tail is not one of them — see
|
|
1235
|
+
* {@link complete}.
|
|
1236
|
+
*/
|
|
1237
|
+
finish() {
|
|
1238
|
+
return this.records;
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
var SEEKING = 0;
|
|
1242
|
+
var COUNTING = 1;
|
|
1243
|
+
var CLOSED = 2;
|
|
1244
|
+
var JsonArrayRecordCounter = class {
|
|
1245
|
+
constructor() {
|
|
1246
|
+
this.depth = 0;
|
|
1247
|
+
this.inString = false;
|
|
1248
|
+
this.escaped = false;
|
|
1249
|
+
this.topIsObject = false;
|
|
1250
|
+
this.state = SEEKING;
|
|
1251
|
+
this.count = 0;
|
|
1252
|
+
}
|
|
1253
|
+
push(chunk) {
|
|
1254
|
+
if (this.state === CLOSED) return;
|
|
1255
|
+
let { depth, inString, escaped, topIsObject, count } = this;
|
|
1256
|
+
let state = this.state;
|
|
1257
|
+
for (const byte of chunk) {
|
|
1258
|
+
if (inString) {
|
|
1259
|
+
if (escaped) escaped = false;
|
|
1260
|
+
else if (byte === BACKSLASH) escaped = true;
|
|
1261
|
+
else if (byte === QUOTE) inString = false;
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
if (byte === QUOTE) {
|
|
1265
|
+
inString = true;
|
|
1266
|
+
} else if (byte === OPEN_BRACE || byte === OPEN_BRACKET) {
|
|
1267
|
+
if (depth === 0 && byte === OPEN_BRACE) topIsObject = true;
|
|
1268
|
+
if (byte === OPEN_BRACKET && depth === 1 && topIsObject && state === SEEKING) {
|
|
1269
|
+
state = COUNTING;
|
|
1270
|
+
}
|
|
1271
|
+
depth++;
|
|
1272
|
+
} else if (byte === CLOSE_BRACE || byte === CLOSE_BRACKET) {
|
|
1273
|
+
depth--;
|
|
1274
|
+
if (state === COUNTING) {
|
|
1275
|
+
if (depth === 2) count++;
|
|
1276
|
+
else if (depth === 1) {
|
|
1277
|
+
state = CLOSED;
|
|
1278
|
+
break;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
this.depth = depth;
|
|
1284
|
+
this.inString = inString;
|
|
1285
|
+
this.escaped = escaped;
|
|
1286
|
+
this.topIsObject = topIsObject;
|
|
1287
|
+
this.state = state;
|
|
1288
|
+
this.count = count;
|
|
1289
|
+
}
|
|
1290
|
+
get records() {
|
|
1291
|
+
return this.count;
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Whether the rows array has closed. What follows it is checked by parsing
|
|
1295
|
+
* the whole document, which a cut-off body fails.
|
|
1296
|
+
*/
|
|
1297
|
+
get complete() {
|
|
1298
|
+
return this.state === CLOSED;
|
|
1299
|
+
}
|
|
1300
|
+
finish() {
|
|
1301
|
+
return this.count;
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
// src/exportDownload.ts
|
|
1306
|
+
var RECORD_COUNT_HEADER = "x-delopay-record-count";
|
|
1307
|
+
var LIST_ENVELOPE = { rows: "records", count: "record_count" };
|
|
1308
|
+
var WORKSPACE_ENVELOPE = { rows: "data", count: "total_count" };
|
|
1309
|
+
function parseRecordCount(header) {
|
|
1310
|
+
if (header === null) return null;
|
|
1311
|
+
const trimmed = header.trim();
|
|
1312
|
+
if (!/^\d+$/.test(trimmed)) return null;
|
|
1313
|
+
const value = Number(trimmed);
|
|
1314
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
1315
|
+
}
|
|
1316
|
+
function counterFor(format) {
|
|
1317
|
+
if (format === "csv") return new CsvRecordCounter();
|
|
1318
|
+
if (format === "json") return new JsonArrayRecordCounter();
|
|
1319
|
+
return null;
|
|
1320
|
+
}
|
|
1321
|
+
function isRecord(value) {
|
|
1322
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1323
|
+
}
|
|
1324
|
+
function announced(expected) {
|
|
1325
|
+
return expected === null ? "" : ` of the ${expected} announced`;
|
|
1326
|
+
}
|
|
1327
|
+
function incomplete(message, expected, received, requestId) {
|
|
1328
|
+
return new DelopayError(message, {
|
|
1329
|
+
status: 0,
|
|
1330
|
+
code: "EXPORT_INCOMPLETE",
|
|
1331
|
+
type: "export_incomplete",
|
|
1332
|
+
...requestId !== void 0 ? { requestId } : {},
|
|
1333
|
+
data: { expected_records: expected, received_records: received }
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
async function downloadExport(request, call, options) {
|
|
1337
|
+
const { format } = call;
|
|
1338
|
+
const envelope = call.envelope ?? LIST_ENVELOPE;
|
|
1339
|
+
const onProgress = options?.onProgress;
|
|
1340
|
+
let latest = {
|
|
1341
|
+
phase: "preparing",
|
|
1342
|
+
receivedBytes: 0,
|
|
1343
|
+
totalBytes: null,
|
|
1344
|
+
receivedRecords: 0,
|
|
1345
|
+
expectedRecords: null
|
|
1346
|
+
};
|
|
1347
|
+
const seen = { attempt: -1, counter: null, expected: null, requestId: void 0, listenerError: null };
|
|
1348
|
+
const report = (progress) => {
|
|
1349
|
+
latest = progress;
|
|
1350
|
+
if (!onProgress) return;
|
|
1351
|
+
try {
|
|
1352
|
+
onProgress({ ...progress });
|
|
1353
|
+
} catch (error) {
|
|
1354
|
+
seen.listenerError = { error };
|
|
1355
|
+
throw error;
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
report(latest);
|
|
1359
|
+
const onDownloadProgress = (event) => {
|
|
1360
|
+
if (event.attempt !== seen.attempt) {
|
|
1361
|
+
seen.attempt = event.attempt;
|
|
1362
|
+
seen.counter = counterFor(format);
|
|
1363
|
+
seen.expected = format === "pdf" ? null : parseRecordCount(event.headers.get(RECORD_COUNT_HEADER));
|
|
1364
|
+
seen.requestId = event.headers.get("x-request-id") ?? event.headers.get("x-trace-id") ?? void 0;
|
|
1365
|
+
}
|
|
1366
|
+
if (event.chunk.byteLength > 0) seen.counter?.push(event.chunk);
|
|
1367
|
+
report({
|
|
1368
|
+
phase: "receiving",
|
|
1369
|
+
receivedBytes: event.loaded,
|
|
1370
|
+
totalBytes: event.total,
|
|
1371
|
+
receivedRecords: seen.counter?.records ?? 0,
|
|
1372
|
+
expectedRecords: seen.expected
|
|
1373
|
+
});
|
|
1374
|
+
};
|
|
1375
|
+
let result;
|
|
1376
|
+
try {
|
|
1377
|
+
result = await request(call.method, call.path, {
|
|
1378
|
+
...call.request,
|
|
1379
|
+
...options?.signal !== void 0 ? { signal: options.signal } : {},
|
|
1380
|
+
...options?.timeout !== void 0 ? { timeout: options.timeout } : {},
|
|
1381
|
+
onDownloadProgress
|
|
1382
|
+
});
|
|
1383
|
+
} catch (err) {
|
|
1384
|
+
if (seen.listenerError !== null && err === seen.listenerError.error) throw err;
|
|
1385
|
+
if (format === "json" && seen.attempt >= 0 && err instanceof SyntaxError) {
|
|
1386
|
+
const received2 = seen.counter?.records ?? 0;
|
|
1387
|
+
throw incomplete(
|
|
1388
|
+
seen.expected === null ? `Export incomplete: the body ended part-way through the JSON document, after ${received2} records` : `Export incomplete: the server announced ${seen.expected} records, and the body ended part-way through the JSON document after ${received2}`,
|
|
1389
|
+
seen.expected,
|
|
1390
|
+
received2,
|
|
1391
|
+
seen.requestId
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
throw err;
|
|
1395
|
+
}
|
|
1396
|
+
const { expected, requestId } = seen;
|
|
1397
|
+
let received = 0;
|
|
1398
|
+
if (format === "json") {
|
|
1399
|
+
const rows = isRecord(result) ? result[envelope.rows] : void 0;
|
|
1400
|
+
if (!Array.isArray(rows)) {
|
|
1401
|
+
throw incomplete(
|
|
1402
|
+
`Export incomplete: the body is not an export envelope with a "${envelope.rows}" array, so it carries 0 records${announced(expected)}`,
|
|
1403
|
+
expected,
|
|
1404
|
+
0,
|
|
1405
|
+
requestId
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1408
|
+
received = rows.length;
|
|
1409
|
+
const declared = isRecord(result) ? result[envelope.count] : void 0;
|
|
1410
|
+
if (typeof declared === "number" && declared !== rows.length) {
|
|
1411
|
+
throw incomplete(
|
|
1412
|
+
`Export incomplete: the file's ${envelope.count} is ${declared}, but it carries ${rows.length} records`,
|
|
1413
|
+
declared,
|
|
1414
|
+
rows.length,
|
|
1415
|
+
requestId
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
} else if (format === "csv") {
|
|
1419
|
+
const counter = seen.counter;
|
|
1420
|
+
received = counter?.finish() ?? 0;
|
|
1421
|
+
if (!counter?.complete) {
|
|
1422
|
+
throw incomplete(
|
|
1423
|
+
`Export incomplete: the CSV body ended part-way through a line, after ${received} complete records${announced(expected)}`,
|
|
1424
|
+
expected,
|
|
1425
|
+
received,
|
|
1426
|
+
requestId
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
if (expected !== null && received !== expected) {
|
|
1431
|
+
throw incomplete(
|
|
1432
|
+
`Export incomplete: the server announced ${expected} records, and the body carried ${received}`,
|
|
1433
|
+
expected,
|
|
1434
|
+
received,
|
|
1435
|
+
requestId
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
report({
|
|
1439
|
+
phase: "done",
|
|
1440
|
+
receivedBytes: latest.receivedBytes,
|
|
1441
|
+
totalBytes: latest.totalBytes,
|
|
1442
|
+
receivedRecords: received,
|
|
1443
|
+
expectedRecords: expected
|
|
1444
|
+
});
|
|
1445
|
+
return result;
|
|
1446
|
+
}
|
|
1447
|
+
var ACCEPT = {
|
|
1448
|
+
csv: "text/csv",
|
|
1449
|
+
json: "application/json",
|
|
1450
|
+
pdf: "application/pdf"
|
|
1451
|
+
};
|
|
1452
|
+
function negotiated(options, format) {
|
|
1453
|
+
const headers = { ...options.headers, Accept: ACCEPT[format] };
|
|
1454
|
+
return format === "json" ? { ...options, headers } : { ...options, headers, responseType: "blob" };
|
|
1455
|
+
}
|
|
1456
|
+
function runExport(request, method, path, base, options) {
|
|
1457
|
+
const format = options?.format ?? "json";
|
|
1458
|
+
return downloadExport(
|
|
1459
|
+
request,
|
|
1460
|
+
{ method, path, request: negotiated(base, format), format },
|
|
1461
|
+
options
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1182
1465
|
// src/resources/disputes.ts
|
|
1183
1466
|
function workspaceQuery(params) {
|
|
1184
1467
|
if (!params) return void 0;
|
|
@@ -1207,9 +1490,28 @@ var Disputes = class {
|
|
|
1207
1490
|
async workspaceAggregate(params) {
|
|
1208
1491
|
return this.request("GET", "/disputes/workspace/aggregate", { query: workspaceQuery(params) });
|
|
1209
1492
|
}
|
|
1210
|
-
/**
|
|
1211
|
-
|
|
1212
|
-
|
|
1493
|
+
/**
|
|
1494
|
+
* Export the complete filtered set, or throw on the server's explicit
|
|
1495
|
+
* export-limit refusal. `GET /disputes/workspace/export`
|
|
1496
|
+
*
|
|
1497
|
+
* The body is streamed, and held to the `X-Delopay-Record-Count` the server
|
|
1498
|
+
* announces and to its own `total_count`: a set that arrives short rejects
|
|
1499
|
+
* with `EXPORT_INCOMPLETE` rather than resolving. `options` reports the
|
|
1500
|
+
* download's progress and takes a signal and an idle timeout — see
|
|
1501
|
+
* {@link ExportTransferOptions}.
|
|
1502
|
+
*/
|
|
1503
|
+
async workspaceExport(params, options) {
|
|
1504
|
+
return downloadExport(
|
|
1505
|
+
this.request,
|
|
1506
|
+
{
|
|
1507
|
+
method: "GET",
|
|
1508
|
+
path: "/disputes/workspace/export",
|
|
1509
|
+
request: { query: workspaceQuery(params) },
|
|
1510
|
+
format: "json",
|
|
1511
|
+
envelope: WORKSPACE_ENVELOPE
|
|
1512
|
+
},
|
|
1513
|
+
options
|
|
1514
|
+
);
|
|
1213
1515
|
}
|
|
1214
1516
|
/**
|
|
1215
1517
|
* Retrieve a dispute by its ID.
|
|
@@ -4366,77 +4668,68 @@ var Export = class {
|
|
|
4366
4668
|
this.request = request;
|
|
4367
4669
|
}
|
|
4368
4670
|
async transactions(params, options) {
|
|
4369
|
-
return this.request
|
|
4370
|
-
"POST",
|
|
4371
|
-
"/export/transactions",
|
|
4372
|
-
transactionBody(params, options)
|
|
4373
|
-
);
|
|
4671
|
+
return runExport(this.request, "POST", "/export/transactions", { body: params ?? {} }, options);
|
|
4374
4672
|
}
|
|
4375
4673
|
async transactionsForProfile(params, options) {
|
|
4376
|
-
return
|
|
4674
|
+
return runExport(
|
|
4675
|
+
this.request,
|
|
4377
4676
|
"POST",
|
|
4378
4677
|
"/export/profile/transactions",
|
|
4379
|
-
|
|
4678
|
+
{ body: params ?? {} },
|
|
4679
|
+
options
|
|
4380
4680
|
);
|
|
4381
4681
|
}
|
|
4382
4682
|
async refunds(params, options) {
|
|
4383
|
-
return this.request
|
|
4683
|
+
return runExport(this.request, "POST", "/refunds/list/export", { body: params ?? {} }, options);
|
|
4384
4684
|
}
|
|
4385
4685
|
async refundsForProfile(params, options) {
|
|
4386
|
-
return
|
|
4686
|
+
return runExport(
|
|
4687
|
+
this.request,
|
|
4387
4688
|
"POST",
|
|
4388
4689
|
"/refunds/profile/list/export",
|
|
4389
|
-
|
|
4690
|
+
{ body: params ?? {} },
|
|
4691
|
+
options
|
|
4390
4692
|
);
|
|
4391
4693
|
}
|
|
4392
4694
|
async disputes(params, options) {
|
|
4393
|
-
return this.request
|
|
4695
|
+
return runExport(this.request, "GET", "/disputes/list/export", queried(params), options);
|
|
4394
4696
|
}
|
|
4395
4697
|
async disputesForProfile(params, options) {
|
|
4396
|
-
return
|
|
4698
|
+
return runExport(
|
|
4699
|
+
this.request,
|
|
4397
4700
|
"GET",
|
|
4398
4701
|
"/disputes/profile/list/export",
|
|
4399
|
-
queried(params,
|
|
4702
|
+
queried(params),
|
|
4703
|
+
options
|
|
4400
4704
|
);
|
|
4401
4705
|
}
|
|
4402
4706
|
async payouts(params, options) {
|
|
4403
|
-
return this.request
|
|
4707
|
+
return runExport(this.request, "POST", "/payouts/list/export", { body: params }, options);
|
|
4404
4708
|
}
|
|
4405
4709
|
async payoutsForProfile(params, options) {
|
|
4406
|
-
return
|
|
4710
|
+
return runExport(
|
|
4711
|
+
this.request,
|
|
4712
|
+
"POST",
|
|
4713
|
+
"/payouts/profile/list/export",
|
|
4714
|
+
{ body: params },
|
|
4715
|
+
options
|
|
4716
|
+
);
|
|
4407
4717
|
}
|
|
4408
4718
|
async subscriptions(profileId, params, options) {
|
|
4409
|
-
return
|
|
4719
|
+
return runExport(
|
|
4720
|
+
this.request,
|
|
4410
4721
|
"GET",
|
|
4411
4722
|
"/subscriptions/list/export",
|
|
4412
|
-
queried(params,
|
|
4723
|
+
queried(params, { "X-Profile-Id": profileId }),
|
|
4724
|
+
options
|
|
4413
4725
|
);
|
|
4414
4726
|
}
|
|
4415
4727
|
async auditLog(params, options) {
|
|
4416
|
-
return this.request
|
|
4728
|
+
return runExport(this.request, "GET", "/audit/export", queried(params), options);
|
|
4417
4729
|
}
|
|
4418
4730
|
};
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
json: "application/json",
|
|
4422
|
-
pdf: "application/pdf"
|
|
4423
|
-
};
|
|
4424
|
-
function negotiated(options, format) {
|
|
4425
|
-
const headers = { ...options.headers, Accept: ACCEPT[format] };
|
|
4426
|
-
return format === "json" ? { ...options, headers } : { ...options, headers, responseType: "blob" };
|
|
4427
|
-
}
|
|
4428
|
-
function transactionBody(params, options) {
|
|
4429
|
-
const format = options?.format ?? "json";
|
|
4430
|
-
return negotiated({ body: { ...params, format } }, format);
|
|
4431
|
-
}
|
|
4432
|
-
function bodied(body, options) {
|
|
4433
|
-
return negotiated({ body }, options?.format ?? "json");
|
|
4434
|
-
}
|
|
4435
|
-
function queried(params, options, headers) {
|
|
4436
|
-
return negotiated(
|
|
4437
|
-
{ query: params ?? {}, ...headers ? { headers } : {} },
|
|
4438
|
-
options?.format ?? "json"
|
|
4439
|
-
);
|
|
4731
|
+
function queried(params, headers) {
|
|
4732
|
+
return { query: params ?? {}, ...headers ? { headers } : {} };
|
|
4440
4733
|
}
|
|
4441
4734
|
|
|
4442
4735
|
// src/resources/featureMatrix.ts
|
|
@@ -4720,6 +5013,24 @@ var ExternalRecords = class {
|
|
|
4720
5013
|
async create(params) {
|
|
4721
5014
|
return this.request("POST", "/external-records", { body: params });
|
|
4722
5015
|
}
|
|
5016
|
+
/**
|
|
5017
|
+
* What this deployment will accept, per kind.
|
|
5018
|
+
* `GET /external-records/capabilities`
|
|
5019
|
+
*
|
|
5020
|
+
* Read it before offering the operator a form. Every kind is listed, so an
|
|
5021
|
+
* entry that is not served is distinguishable from a kind this release does
|
|
5022
|
+
* not know at all — and `create` says *why* it is not served: a gap
|
|
5023
|
+
* (`not_implemented`) or a rule (`not_applicable`). Treating those as the
|
|
5024
|
+
* same thing is how a caller ends up waiting for something that will never
|
|
5025
|
+
* be built.
|
|
5026
|
+
*
|
|
5027
|
+
* The answer describes the binary rather than anything a merchant owns, so
|
|
5028
|
+
* it is the same for every caller of one deployment and is safe to cache for
|
|
5029
|
+
* the life of a dashboard session.
|
|
5030
|
+
*/
|
|
5031
|
+
async capabilities() {
|
|
5032
|
+
return this.request("GET", "/external-records/capabilities");
|
|
5033
|
+
}
|
|
4723
5034
|
};
|
|
4724
5035
|
|
|
4725
5036
|
// src/resources/products.ts
|
|
@@ -5809,6 +6120,112 @@ function findIdempotencyKey(headers) {
|
|
|
5809
6120
|
}
|
|
5810
6121
|
function noop() {
|
|
5811
6122
|
}
|
|
6123
|
+
var ListenerFailure = class {
|
|
6124
|
+
constructor(cause) {
|
|
6125
|
+
this.cause = cause;
|
|
6126
|
+
}
|
|
6127
|
+
};
|
|
6128
|
+
var BodyStreamFailure = class {
|
|
6129
|
+
constructor(cause) {
|
|
6130
|
+
this.cause = cause;
|
|
6131
|
+
}
|
|
6132
|
+
};
|
|
6133
|
+
function abortError() {
|
|
6134
|
+
const error = new Error("The operation was aborted");
|
|
6135
|
+
error.name = "AbortError";
|
|
6136
|
+
return error;
|
|
6137
|
+
}
|
|
6138
|
+
function parseContentLength(header) {
|
|
6139
|
+
if (header === null || !/^\s*\d+\s*$/.test(header)) return null;
|
|
6140
|
+
const value = Number(header);
|
|
6141
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
6142
|
+
}
|
|
6143
|
+
function readChunk(reader, signal) {
|
|
6144
|
+
if (signal.aborted) return Promise.reject(abortError());
|
|
6145
|
+
return new Promise((resolve, reject) => {
|
|
6146
|
+
const onAbort = () => reject(abortError());
|
|
6147
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6148
|
+
reader.read().then(
|
|
6149
|
+
(result) => {
|
|
6150
|
+
signal.removeEventListener("abort", onAbort);
|
|
6151
|
+
resolve(result);
|
|
6152
|
+
},
|
|
6153
|
+
(cause) => {
|
|
6154
|
+
signal.removeEventListener("abort", onAbort);
|
|
6155
|
+
reject(signal.aborted ? abortError() : new BodyStreamFailure(cause));
|
|
6156
|
+
}
|
|
6157
|
+
);
|
|
6158
|
+
});
|
|
6159
|
+
}
|
|
6160
|
+
function concatChunks(chunks, length) {
|
|
6161
|
+
const out = new Uint8Array(length);
|
|
6162
|
+
let offset = 0;
|
|
6163
|
+
for (const chunk of chunks) {
|
|
6164
|
+
out.set(chunk, offset);
|
|
6165
|
+
offset += chunk.byteLength;
|
|
6166
|
+
}
|
|
6167
|
+
return out.buffer;
|
|
6168
|
+
}
|
|
6169
|
+
async function receiveWithProgress(response, responseType, listener, attempt, signal, onActivity) {
|
|
6170
|
+
const headers = response.headers ?? new Headers();
|
|
6171
|
+
const total = parseContentLength(headers.get("content-length"));
|
|
6172
|
+
let loaded = 0;
|
|
6173
|
+
const notify = (chunk) => {
|
|
6174
|
+
try {
|
|
6175
|
+
listener({ loaded, total, chunk: chunk.slice(), headers, attempt });
|
|
6176
|
+
} catch (cause) {
|
|
6177
|
+
throw new ListenerFailure(cause);
|
|
6178
|
+
}
|
|
6179
|
+
};
|
|
6180
|
+
onActivity();
|
|
6181
|
+
notify(new Uint8Array(0));
|
|
6182
|
+
const body = response.body;
|
|
6183
|
+
if (!body || typeof body.getReader !== "function") {
|
|
6184
|
+
if (responseType === "blob") {
|
|
6185
|
+
const blob = await response.blob();
|
|
6186
|
+
const bytes3 = new Uint8Array(await blob.arrayBuffer());
|
|
6187
|
+
loaded = bytes3.byteLength;
|
|
6188
|
+
if (loaded > 0) notify(bytes3);
|
|
6189
|
+
return blob;
|
|
6190
|
+
}
|
|
6191
|
+
if (responseType === "arraybuffer") {
|
|
6192
|
+
const buffer = await response.arrayBuffer();
|
|
6193
|
+
loaded = buffer.byteLength;
|
|
6194
|
+
if (loaded > 0) notify(new Uint8Array(buffer));
|
|
6195
|
+
return buffer;
|
|
6196
|
+
}
|
|
6197
|
+
const text2 = await response.text();
|
|
6198
|
+
const bytes2 = new TextEncoder().encode(text2);
|
|
6199
|
+
loaded = bytes2.byteLength;
|
|
6200
|
+
if (loaded > 0) notify(bytes2);
|
|
6201
|
+
return text2 ? JSON.parse(text2) : void 0;
|
|
6202
|
+
}
|
|
6203
|
+
const reader = body.getReader();
|
|
6204
|
+
const chunks = [];
|
|
6205
|
+
try {
|
|
6206
|
+
for (; ; ) {
|
|
6207
|
+
const { done, value } = await readChunk(reader, signal);
|
|
6208
|
+
if (done) break;
|
|
6209
|
+
if (!value || value.byteLength === 0) continue;
|
|
6210
|
+
chunks.push(value);
|
|
6211
|
+
loaded += value.byteLength;
|
|
6212
|
+
onActivity();
|
|
6213
|
+
notify(value);
|
|
6214
|
+
}
|
|
6215
|
+
} catch (err) {
|
|
6216
|
+
reader.cancel().catch(noop);
|
|
6217
|
+
throw err;
|
|
6218
|
+
}
|
|
6219
|
+
const bytes = concatChunks(chunks, loaded);
|
|
6220
|
+
if (responseType === "blob") {
|
|
6221
|
+
return new Blob([bytes], { type: headers.get("content-type") ?? "" });
|
|
6222
|
+
}
|
|
6223
|
+
if (responseType === "arraybuffer") {
|
|
6224
|
+
return bytes;
|
|
6225
|
+
}
|
|
6226
|
+
const text = new TextDecoder().decode(bytes);
|
|
6227
|
+
return text ? JSON.parse(text) : void 0;
|
|
6228
|
+
}
|
|
5812
6229
|
function combineSignals(signals) {
|
|
5813
6230
|
const controller = new AbortController();
|
|
5814
6231
|
const listeners = [];
|
|
@@ -6090,7 +6507,12 @@ var Delopay = class {
|
|
|
6090
6507
|
emit("retry", { attempt, maxRetries: this.maxRetries, method, path });
|
|
6091
6508
|
}
|
|
6092
6509
|
const timeoutCtrl = new AbortController();
|
|
6093
|
-
|
|
6510
|
+
let timeoutId = setTimeout(() => timeoutCtrl.abort(), timeoutMs);
|
|
6511
|
+
const restartIdleTimer = () => {
|
|
6512
|
+
if (timeoutCtrl.signal.aborted) return;
|
|
6513
|
+
clearTimeout(timeoutId);
|
|
6514
|
+
timeoutId = setTimeout(() => timeoutCtrl.abort(), timeoutMs);
|
|
6515
|
+
};
|
|
6094
6516
|
const combined = combineSignals(
|
|
6095
6517
|
callerSignal ? [timeoutCtrl.signal, callerSignal] : [timeoutCtrl.signal]
|
|
6096
6518
|
);
|
|
@@ -6148,6 +6570,16 @@ var Delopay = class {
|
|
|
6148
6570
|
}
|
|
6149
6571
|
throw error;
|
|
6150
6572
|
}
|
|
6573
|
+
if (options?.onDownloadProgress) {
|
|
6574
|
+
return await receiveWithProgress(
|
|
6575
|
+
response,
|
|
6576
|
+
options.responseType,
|
|
6577
|
+
options.onDownloadProgress,
|
|
6578
|
+
attempt,
|
|
6579
|
+
combined.signal,
|
|
6580
|
+
restartIdleTimer
|
|
6581
|
+
);
|
|
6582
|
+
}
|
|
6151
6583
|
if (options?.responseType === "blob") {
|
|
6152
6584
|
return await response.blob();
|
|
6153
6585
|
}
|
|
@@ -6160,6 +6592,20 @@ var Delopay = class {
|
|
|
6160
6592
|
if (err instanceof DelopayError || err instanceof DelopayAuthenticationError) {
|
|
6161
6593
|
throw err;
|
|
6162
6594
|
}
|
|
6595
|
+
if (err instanceof ListenerFailure) {
|
|
6596
|
+
throw err.cause;
|
|
6597
|
+
}
|
|
6598
|
+
if (err instanceof BodyStreamFailure) {
|
|
6599
|
+
const cause = err.cause;
|
|
6600
|
+
const detail = cause instanceof Error ? cause.message : String(cause ?? "body stream failed");
|
|
6601
|
+
lastError = new DelopayError(`Network error: ${detail}`, {
|
|
6602
|
+
status: 0,
|
|
6603
|
+
code: "NETWORK",
|
|
6604
|
+
type: "network_error"
|
|
6605
|
+
});
|
|
6606
|
+
if (isRetryable && attempt < this.maxRetries) continue;
|
|
6607
|
+
throw lastError;
|
|
6608
|
+
}
|
|
6163
6609
|
if (err instanceof Error && err.name === "AbortError") {
|
|
6164
6610
|
if (callerSignal?.aborted) {
|
|
6165
6611
|
throw new DelopayError("Request aborted", {
|