@kinosec/cli 0.10.0 → 0.10.2
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/cli.js +1033 -311
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -5383,25 +5383,44 @@ var {
|
|
|
5383
5383
|
// src/lib/errors.ts
|
|
5384
5384
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
5385
5385
|
|
|
5386
|
-
// ../../node_modules/.pnpm/ky@
|
|
5387
|
-
var
|
|
5386
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/KyError.js
|
|
5387
|
+
var KyError = class extends Error {
|
|
5388
|
+
name = "KyError";
|
|
5389
|
+
get isKyError() {
|
|
5390
|
+
return true;
|
|
5391
|
+
}
|
|
5392
|
+
};
|
|
5393
|
+
|
|
5394
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/HTTPError.js
|
|
5395
|
+
var HTTPError = class extends KyError {
|
|
5396
|
+
name = "HTTPError";
|
|
5388
5397
|
response;
|
|
5389
5398
|
request;
|
|
5390
5399
|
options;
|
|
5400
|
+
data;
|
|
5391
5401
|
constructor(response, request, options) {
|
|
5392
5402
|
const code = response.status || response.status === 0 ? response.status : "";
|
|
5393
5403
|
const title = response.statusText ?? "";
|
|
5394
5404
|
const status = `${code} ${title}`.trim();
|
|
5395
5405
|
const reason = status ? `status code ${status}` : "an unknown error";
|
|
5396
5406
|
super(`Request failed with ${reason}: ${request.method} ${request.url}`);
|
|
5397
|
-
this.name = "HTTPError";
|
|
5398
5407
|
this.response = response;
|
|
5399
5408
|
this.request = request;
|
|
5400
5409
|
this.options = options;
|
|
5401
5410
|
}
|
|
5402
5411
|
};
|
|
5403
5412
|
|
|
5404
|
-
// ../../node_modules/.pnpm/ky@
|
|
5413
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/NetworkError.js
|
|
5414
|
+
var NetworkError = class extends KyError {
|
|
5415
|
+
name = "NetworkError";
|
|
5416
|
+
request;
|
|
5417
|
+
constructor(request, options) {
|
|
5418
|
+
super(`Request failed due to a network error: ${request.method} ${request.url}`, options);
|
|
5419
|
+
this.request = request;
|
|
5420
|
+
}
|
|
5421
|
+
};
|
|
5422
|
+
|
|
5423
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/NonError.js
|
|
5405
5424
|
var NonError = class extends Error {
|
|
5406
5425
|
name = "NonError";
|
|
5407
5426
|
value;
|
|
@@ -5420,8 +5439,8 @@ var NonError = class extends Error {
|
|
|
5420
5439
|
}
|
|
5421
5440
|
};
|
|
5422
5441
|
|
|
5423
|
-
// ../../node_modules/.pnpm/ky@
|
|
5424
|
-
var ForceRetryError = class extends
|
|
5442
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/ForceRetryError.js
|
|
5443
|
+
var ForceRetryError = class extends KyError {
|
|
5425
5444
|
name = "ForceRetryError";
|
|
5426
5445
|
customDelay;
|
|
5427
5446
|
code;
|
|
@@ -5435,7 +5454,27 @@ var ForceRetryError = class extends Error {
|
|
|
5435
5454
|
}
|
|
5436
5455
|
};
|
|
5437
5456
|
|
|
5438
|
-
// ../../node_modules/.pnpm/ky@
|
|
5457
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/SchemaValidationError.js
|
|
5458
|
+
var SchemaValidationError = class extends Error {
|
|
5459
|
+
name = "SchemaValidationError";
|
|
5460
|
+
issues;
|
|
5461
|
+
constructor(issues) {
|
|
5462
|
+
super("Response schema validation failed");
|
|
5463
|
+
this.issues = issues;
|
|
5464
|
+
}
|
|
5465
|
+
};
|
|
5466
|
+
|
|
5467
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/TimeoutError.js
|
|
5468
|
+
var TimeoutError = class extends KyError {
|
|
5469
|
+
name = "TimeoutError";
|
|
5470
|
+
request;
|
|
5471
|
+
constructor(request) {
|
|
5472
|
+
super(`Request timed out: ${request.method} ${request.url}`);
|
|
5473
|
+
this.request = request;
|
|
5474
|
+
}
|
|
5475
|
+
};
|
|
5476
|
+
|
|
5477
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/core/constants.js
|
|
5439
5478
|
var supportsRequestStreams = (() => {
|
|
5440
5479
|
let duplexAccessed = false;
|
|
5441
5480
|
let hasContentType = false;
|
|
@@ -5479,7 +5518,7 @@ var responseTypes = {
|
|
|
5479
5518
|
bytes: "*/*"
|
|
5480
5519
|
};
|
|
5481
5520
|
var maxSafeTimeout = 2147483647;
|
|
5482
|
-
var usualFormBoundarySize =
|
|
5521
|
+
var usualFormBoundarySize = 40;
|
|
5483
5522
|
var stop = /* @__PURE__ */ Symbol("stop");
|
|
5484
5523
|
var RetryMarker = class {
|
|
5485
5524
|
options;
|
|
@@ -5493,9 +5532,11 @@ var kyOptionKeys = {
|
|
|
5493
5532
|
parseJson: true,
|
|
5494
5533
|
stringifyJson: true,
|
|
5495
5534
|
searchParams: true,
|
|
5496
|
-
|
|
5535
|
+
baseUrl: true,
|
|
5536
|
+
prefix: true,
|
|
5497
5537
|
retry: true,
|
|
5498
5538
|
timeout: true,
|
|
5539
|
+
totalTimeout: true,
|
|
5499
5540
|
hooks: true,
|
|
5500
5541
|
throwHttpErrors: true,
|
|
5501
5542
|
onDownloadProgress: true,
|
|
@@ -5503,10 +5544,6 @@ var kyOptionKeys = {
|
|
|
5503
5544
|
fetch: true,
|
|
5504
5545
|
context: true
|
|
5505
5546
|
};
|
|
5506
|
-
var vendorSpecificOptions = {
|
|
5507
|
-
next: true
|
|
5508
|
-
// Next.js cache revalidation (revalidate, tags)
|
|
5509
|
-
};
|
|
5510
5547
|
var requestOptionsRegistry = {
|
|
5511
5548
|
method: true,
|
|
5512
5549
|
headers: true,
|
|
@@ -5524,7 +5561,8 @@ var requestOptionsRegistry = {
|
|
|
5524
5561
|
duplex: true
|
|
5525
5562
|
};
|
|
5526
5563
|
|
|
5527
|
-
// ../../node_modules/.pnpm/ky@
|
|
5564
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/body.js
|
|
5565
|
+
var encoder = new TextEncoder();
|
|
5528
5566
|
var getBodySize = (body) => {
|
|
5529
5567
|
if (!body) {
|
|
5530
5568
|
return 0;
|
|
@@ -5533,33 +5571,22 @@ var getBodySize = (body) => {
|
|
|
5533
5571
|
let size = 0;
|
|
5534
5572
|
for (const [key, value] of body) {
|
|
5535
5573
|
size += usualFormBoundarySize;
|
|
5536
|
-
size +=
|
|
5537
|
-
size += typeof value === "string" ?
|
|
5574
|
+
size += encoder.encode(`Content-Disposition: form-data; name="${key}"`).byteLength;
|
|
5575
|
+
size += typeof value === "string" ? encoder.encode(value).byteLength : value.size;
|
|
5538
5576
|
}
|
|
5539
5577
|
return size;
|
|
5540
5578
|
}
|
|
5541
5579
|
if (body instanceof Blob) {
|
|
5542
5580
|
return body.size;
|
|
5543
5581
|
}
|
|
5544
|
-
if (body instanceof ArrayBuffer) {
|
|
5582
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
|
|
5545
5583
|
return body.byteLength;
|
|
5546
5584
|
}
|
|
5547
5585
|
if (typeof body === "string") {
|
|
5548
|
-
return
|
|
5586
|
+
return encoder.encode(body).byteLength;
|
|
5549
5587
|
}
|
|
5550
5588
|
if (body instanceof URLSearchParams) {
|
|
5551
|
-
return
|
|
5552
|
-
}
|
|
5553
|
-
if ("byteLength" in body) {
|
|
5554
|
-
return body.byteLength;
|
|
5555
|
-
}
|
|
5556
|
-
if (typeof body === "object" && body !== null) {
|
|
5557
|
-
try {
|
|
5558
|
-
const jsonString = JSON.stringify(body);
|
|
5559
|
-
return new TextEncoder().encode(jsonString).length;
|
|
5560
|
-
} catch {
|
|
5561
|
-
return 0;
|
|
5562
|
-
}
|
|
5589
|
+
return encoder.encode(body.toString()).byteLength;
|
|
5563
5590
|
}
|
|
5564
5591
|
return 0;
|
|
5565
5592
|
};
|
|
@@ -5591,19 +5618,16 @@ var streamResponse = (response, onDownloadProgress) => {
|
|
|
5591
5618
|
if (!response.body) {
|
|
5592
5619
|
return response;
|
|
5593
5620
|
}
|
|
5594
|
-
|
|
5595
|
-
return new Response(null, {
|
|
5596
|
-
status: response.status,
|
|
5597
|
-
statusText: response.statusText,
|
|
5598
|
-
headers: response.headers
|
|
5599
|
-
});
|
|
5600
|
-
}
|
|
5601
|
-
const totalBytes = Math.max(0, Number(response.headers.get("content-length")) || 0);
|
|
5602
|
-
return new Response(withProgress(response.body, totalBytes, onDownloadProgress), {
|
|
5621
|
+
const responseInit = {
|
|
5603
5622
|
status: response.status,
|
|
5604
5623
|
statusText: response.statusText,
|
|
5605
5624
|
headers: response.headers
|
|
5606
|
-
}
|
|
5625
|
+
};
|
|
5626
|
+
if (response.status === 204) {
|
|
5627
|
+
return new Response(null, responseInit);
|
|
5628
|
+
}
|
|
5629
|
+
const totalBytes = Math.max(0, Number(response.headers.get("content-length")) || 0);
|
|
5630
|
+
return new Response(withProgress(response.body, totalBytes, onDownloadProgress), responseInit);
|
|
5607
5631
|
};
|
|
5608
5632
|
var streamRequest = (request, onUploadProgress, originalBody) => {
|
|
5609
5633
|
if (!request.body) {
|
|
@@ -5617,10 +5641,18 @@ var streamRequest = (request, onUploadProgress, originalBody) => {
|
|
|
5617
5641
|
});
|
|
5618
5642
|
};
|
|
5619
5643
|
|
|
5620
|
-
// ../../node_modules/.pnpm/ky@
|
|
5644
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/is.js
|
|
5621
5645
|
var isObject = (value) => value !== null && typeof value === "object";
|
|
5622
5646
|
|
|
5623
|
-
// ../../node_modules/.pnpm/ky@
|
|
5647
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/merge.js
|
|
5648
|
+
var replaceSymbol = /* @__PURE__ */ Symbol("replaceOption");
|
|
5649
|
+
var getReplaceState = (value) => isObject(value) && value[replaceSymbol] === true ? {
|
|
5650
|
+
isReplace: true,
|
|
5651
|
+
value: value.value
|
|
5652
|
+
} : {
|
|
5653
|
+
isReplace: false,
|
|
5654
|
+
value
|
|
5655
|
+
};
|
|
5624
5656
|
var validateAndMerge = (...sources) => {
|
|
5625
5657
|
for (const source of sources) {
|
|
5626
5658
|
if ((!isObject(source) || Array.isArray(source)) && source !== void 0) {
|
|
@@ -5642,17 +5674,55 @@ var mergeHeaders = (source1 = {}, source2 = {}) => {
|
|
|
5642
5674
|
}
|
|
5643
5675
|
return result;
|
|
5644
5676
|
};
|
|
5677
|
+
var isPlainObject = (value) => {
|
|
5678
|
+
if (!isObject(value) || Array.isArray(value)) {
|
|
5679
|
+
return false;
|
|
5680
|
+
}
|
|
5681
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5682
|
+
return prototype === Object.prototype || prototype === null;
|
|
5683
|
+
};
|
|
5684
|
+
var cloneShallow = (value) => {
|
|
5685
|
+
if (value instanceof URLSearchParams) {
|
|
5686
|
+
const copy = new URLSearchParams(value);
|
|
5687
|
+
const deleted = value[deletedParametersSymbol];
|
|
5688
|
+
if (deleted) {
|
|
5689
|
+
copy[deletedParametersSymbol] = new Set(deleted);
|
|
5690
|
+
}
|
|
5691
|
+
return copy;
|
|
5692
|
+
}
|
|
5693
|
+
if (value instanceof globalThis.Headers) {
|
|
5694
|
+
return new globalThis.Headers(value);
|
|
5695
|
+
}
|
|
5696
|
+
if (Array.isArray(value)) {
|
|
5697
|
+
return [...value];
|
|
5698
|
+
}
|
|
5699
|
+
if (isPlainObject(value)) {
|
|
5700
|
+
const copy = { ...value };
|
|
5701
|
+
return copy;
|
|
5702
|
+
}
|
|
5703
|
+
return value;
|
|
5704
|
+
};
|
|
5705
|
+
var normalizeHeaderObject = (headers) => Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] !== void 0));
|
|
5706
|
+
var mergeHeaderContainers = (source1, source2) => {
|
|
5707
|
+
if (isPlainObject(source1) && isPlainObject(source2)) {
|
|
5708
|
+
return normalizeHeaderObject({ ...source1, ...source2 });
|
|
5709
|
+
}
|
|
5710
|
+
return mergeHeaders(source1, source2);
|
|
5711
|
+
};
|
|
5645
5712
|
function newHookValue(original, incoming, property) {
|
|
5646
5713
|
return Object.hasOwn(incoming, property) && incoming[property] === void 0 ? [] : deepMerge(original[property] ?? [], incoming[property] ?? []);
|
|
5647
5714
|
}
|
|
5648
5715
|
var mergeHooks = (original = {}, incoming = {}) => ({
|
|
5716
|
+
init: newHookValue(original, incoming, "init"),
|
|
5649
5717
|
beforeRequest: newHookValue(original, incoming, "beforeRequest"),
|
|
5650
5718
|
beforeRetry: newHookValue(original, incoming, "beforeRetry"),
|
|
5651
|
-
|
|
5652
|
-
|
|
5719
|
+
beforeError: newHookValue(original, incoming, "beforeError"),
|
|
5720
|
+
afterResponse: newHookValue(original, incoming, "afterResponse")
|
|
5653
5721
|
});
|
|
5722
|
+
var deletedParametersSymbol = /* @__PURE__ */ Symbol("deletedParameters");
|
|
5654
5723
|
var appendSearchParameters = (target, source) => {
|
|
5655
5724
|
const result = new URLSearchParams();
|
|
5725
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
5656
5726
|
for (const input of [target, source]) {
|
|
5657
5727
|
if (input === void 0) {
|
|
5658
5728
|
continue;
|
|
@@ -5660,6 +5730,14 @@ var appendSearchParameters = (target, source) => {
|
|
|
5660
5730
|
if (input instanceof URLSearchParams) {
|
|
5661
5731
|
for (const [key, value] of input.entries()) {
|
|
5662
5732
|
result.append(key, value);
|
|
5733
|
+
deleted.delete(key);
|
|
5734
|
+
}
|
|
5735
|
+
const inputDeleted = input[deletedParametersSymbol];
|
|
5736
|
+
if (inputDeleted) {
|
|
5737
|
+
for (const key of inputDeleted) {
|
|
5738
|
+
result.delete(key);
|
|
5739
|
+
deleted.add(key);
|
|
5740
|
+
}
|
|
5663
5741
|
}
|
|
5664
5742
|
} else if (Array.isArray(input)) {
|
|
5665
5743
|
for (const pair of input) {
|
|
@@ -5667,20 +5745,29 @@ var appendSearchParameters = (target, source) => {
|
|
|
5667
5745
|
throw new TypeError("Array search parameters must be provided in [[key, value], ...] format");
|
|
5668
5746
|
}
|
|
5669
5747
|
result.append(String(pair[0]), String(pair[1]));
|
|
5748
|
+
deleted.delete(String(pair[0]));
|
|
5670
5749
|
}
|
|
5671
5750
|
} else if (isObject(input)) {
|
|
5672
5751
|
for (const [key, value] of Object.entries(input)) {
|
|
5673
|
-
if (value
|
|
5752
|
+
if (value === void 0) {
|
|
5753
|
+
result.delete(key);
|
|
5754
|
+
deleted.add(key);
|
|
5755
|
+
} else {
|
|
5674
5756
|
result.append(key, String(value));
|
|
5757
|
+
deleted.delete(key);
|
|
5675
5758
|
}
|
|
5676
5759
|
}
|
|
5677
5760
|
} else {
|
|
5678
5761
|
const parameters = new URLSearchParams(input);
|
|
5679
5762
|
for (const [key, value] of parameters.entries()) {
|
|
5680
5763
|
result.append(key, value);
|
|
5764
|
+
deleted.delete(key);
|
|
5681
5765
|
}
|
|
5682
5766
|
}
|
|
5683
5767
|
}
|
|
5768
|
+
if (deleted.size > 0) {
|
|
5769
|
+
result[deletedParametersSymbol] = deleted;
|
|
5770
|
+
}
|
|
5684
5771
|
return result;
|
|
5685
5772
|
};
|
|
5686
5773
|
var deepMerge = (...sources) => {
|
|
@@ -5701,35 +5788,42 @@ var deepMerge = (...sources) => {
|
|
|
5701
5788
|
signals2.push(value);
|
|
5702
5789
|
continue;
|
|
5703
5790
|
}
|
|
5791
|
+
const replaceState = getReplaceState(value);
|
|
5792
|
+
const { isReplace } = replaceState;
|
|
5793
|
+
value = replaceState.value;
|
|
5704
5794
|
if (key === "context") {
|
|
5705
5795
|
if (value !== void 0 && value !== null && (!isObject(value) || Array.isArray(value))) {
|
|
5706
5796
|
throw new TypeError("The `context` option must be an object");
|
|
5707
5797
|
}
|
|
5708
5798
|
returnValue = {
|
|
5709
5799
|
...returnValue,
|
|
5710
|
-
context: value === void 0 || value === null ? {} : { ...returnValue.context, ...value }
|
|
5800
|
+
context: value === void 0 || value === null ? {} : isReplace ? { ...value } : { ...returnValue.context, ...value }
|
|
5711
5801
|
};
|
|
5712
5802
|
continue;
|
|
5713
5803
|
}
|
|
5714
5804
|
if (key === "searchParams") {
|
|
5715
5805
|
if (value === void 0 || value === null) {
|
|
5716
5806
|
searchParameters = void 0;
|
|
5807
|
+
} else if (isReplace) {
|
|
5808
|
+
searchParameters = value;
|
|
5717
5809
|
} else {
|
|
5718
5810
|
searchParameters = searchParameters === void 0 ? value : appendSearchParameters(searchParameters, value);
|
|
5719
5811
|
}
|
|
5720
5812
|
continue;
|
|
5721
5813
|
}
|
|
5722
|
-
if (isObject(value) && key in returnValue) {
|
|
5814
|
+
if (isObject(value) && !isReplace && key in returnValue) {
|
|
5723
5815
|
value = deepMerge(returnValue[key], value);
|
|
5724
5816
|
}
|
|
5725
5817
|
returnValue = { ...returnValue, [key]: value };
|
|
5726
5818
|
}
|
|
5727
5819
|
if (isObject(source.hooks)) {
|
|
5728
|
-
|
|
5820
|
+
const { value: hookValue, isReplace } = getReplaceState(source.hooks);
|
|
5821
|
+
hooks = isReplace ? mergeHooks({}, hookValue) : mergeHooks(hooks, hookValue);
|
|
5729
5822
|
returnValue.hooks = hooks;
|
|
5730
5823
|
}
|
|
5731
5824
|
if (isObject(source.headers)) {
|
|
5732
|
-
|
|
5825
|
+
const { value: headerValue, isReplace } = getReplaceState(source.headers);
|
|
5826
|
+
headers = isReplace ? cloneShallow(headerValue) : mergeHeaderContainers(headers, headerValue);
|
|
5733
5827
|
returnValue.headers = headers;
|
|
5734
5828
|
}
|
|
5735
5829
|
}
|
|
@@ -5749,7 +5843,7 @@ var deepMerge = (...sources) => {
|
|
|
5749
5843
|
return returnValue;
|
|
5750
5844
|
};
|
|
5751
5845
|
|
|
5752
|
-
// ../../node_modules/.pnpm/ky@
|
|
5846
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/normalize.js
|
|
5753
5847
|
var normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
|
|
5754
5848
|
var retryMethods = ["get", "put", "head", "delete", "options", "trace"];
|
|
5755
5849
|
var retryStatusCodes = [408, 413, 429, 500, 502, 503, 504];
|
|
@@ -5775,28 +5869,20 @@ var normalizeRetryOptions = (retry2 = {}) => {
|
|
|
5775
5869
|
if (retry2.methods && !Array.isArray(retry2.methods)) {
|
|
5776
5870
|
throw new Error("retry.methods must be an array");
|
|
5777
5871
|
}
|
|
5778
|
-
retry2.methods &&= retry2.methods.map((method) => method.toLowerCase());
|
|
5779
5872
|
if (retry2.statusCodes && !Array.isArray(retry2.statusCodes)) {
|
|
5780
5873
|
throw new Error("retry.statusCodes must be an array");
|
|
5781
5874
|
}
|
|
5782
|
-
const normalizedRetry = Object.fromEntries(Object.entries(
|
|
5875
|
+
const normalizedRetry = Object.fromEntries(Object.entries({
|
|
5876
|
+
...retry2,
|
|
5877
|
+
methods: retry2.methods?.map((method) => method.toLowerCase())
|
|
5878
|
+
}).filter(([, value]) => value !== void 0));
|
|
5783
5879
|
return {
|
|
5784
5880
|
...defaultRetryOptions,
|
|
5785
5881
|
...normalizedRetry
|
|
5786
5882
|
};
|
|
5787
5883
|
};
|
|
5788
5884
|
|
|
5789
|
-
// ../../node_modules/.pnpm/ky@
|
|
5790
|
-
var TimeoutError = class extends Error {
|
|
5791
|
-
request;
|
|
5792
|
-
constructor(request) {
|
|
5793
|
-
super(`Request timed out: ${request.method} ${request.url}`);
|
|
5794
|
-
this.name = "TimeoutError";
|
|
5795
|
-
this.request = request;
|
|
5796
|
-
}
|
|
5797
|
-
};
|
|
5798
|
-
|
|
5799
|
-
// ../../node_modules/.pnpm/ky@1.14.3/node_modules/ky/distribution/utils/timeout.js
|
|
5885
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/timeout.js
|
|
5800
5886
|
async function timeout(request, init, abortController, options) {
|
|
5801
5887
|
return new Promise((resolve, reject) => {
|
|
5802
5888
|
const timeoutId = setTimeout(() => {
|
|
@@ -5811,7 +5897,7 @@ async function timeout(request, init, abortController, options) {
|
|
|
5811
5897
|
});
|
|
5812
5898
|
}
|
|
5813
5899
|
|
|
5814
|
-
// ../../node_modules/.pnpm/ky@
|
|
5900
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/delay.js
|
|
5815
5901
|
async function delay(ms, { signal }) {
|
|
5816
5902
|
return new Promise((resolve, reject) => {
|
|
5817
5903
|
if (signal) {
|
|
@@ -5829,14 +5915,14 @@ async function delay(ms, { signal }) {
|
|
|
5829
5915
|
});
|
|
5830
5916
|
}
|
|
5831
5917
|
|
|
5832
|
-
// ../../node_modules/.pnpm/ky@
|
|
5833
|
-
var findUnknownOptions = (
|
|
5918
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/options.js
|
|
5919
|
+
var findUnknownOptions = (options) => {
|
|
5834
5920
|
const unknownOptions = {};
|
|
5835
5921
|
for (const key in options) {
|
|
5836
5922
|
if (!Object.hasOwn(options, key)) {
|
|
5837
5923
|
continue;
|
|
5838
5924
|
}
|
|
5839
|
-
if (!(key in requestOptionsRegistry) && !(key in kyOptionKeys)
|
|
5925
|
+
if (!(key in requestOptionsRegistry) && !(key in kyOptionKeys)) {
|
|
5840
5926
|
unknownOptions[key] = options[key];
|
|
5841
5927
|
}
|
|
5842
5928
|
}
|
|
@@ -5850,7 +5936,7 @@ var hasSearchParameters = (search) => {
|
|
|
5850
5936
|
return search.length > 0;
|
|
5851
5937
|
}
|
|
5852
5938
|
if (search instanceof URLSearchParams) {
|
|
5853
|
-
return search.size > 0;
|
|
5939
|
+
return search.size > 0 || Boolean(search[deletedParametersSymbol]?.size);
|
|
5854
5940
|
}
|
|
5855
5941
|
if (typeof search === "object") {
|
|
5856
5942
|
return Object.keys(search).length > 0;
|
|
@@ -5861,56 +5947,181 @@ var hasSearchParameters = (search) => {
|
|
|
5861
5947
|
return Boolean(search);
|
|
5862
5948
|
};
|
|
5863
5949
|
|
|
5864
|
-
// ../../node_modules/.pnpm/ky@
|
|
5950
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/is-network-error.js
|
|
5951
|
+
var objectToString = Object.prototype.toString;
|
|
5952
|
+
var isError = (value) => objectToString.call(value) === "[object Error]";
|
|
5953
|
+
var errorMessages = /* @__PURE__ */ new Set([
|
|
5954
|
+
"network error",
|
|
5955
|
+
// Chrome
|
|
5956
|
+
"NetworkError when attempting to fetch resource.",
|
|
5957
|
+
// Firefox
|
|
5958
|
+
"The Internet connection appears to be offline.",
|
|
5959
|
+
// Safari 16
|
|
5960
|
+
"Network request failed",
|
|
5961
|
+
// `cross-fetch`
|
|
5962
|
+
"fetch failed",
|
|
5963
|
+
// Undici (Node.js)
|
|
5964
|
+
"terminated",
|
|
5965
|
+
// Undici (Node.js)
|
|
5966
|
+
" A network error occurred.",
|
|
5967
|
+
// Bun (WebKit) - leading space is intentional
|
|
5968
|
+
"Network connection lost"
|
|
5969
|
+
// Cloudflare Workers (fetch)
|
|
5970
|
+
]);
|
|
5971
|
+
function isRawNetworkError(error2) {
|
|
5972
|
+
const isValid = error2 && isError(error2) && error2.name === "TypeError" && typeof error2.message === "string";
|
|
5973
|
+
if (!isValid) {
|
|
5974
|
+
return false;
|
|
5975
|
+
}
|
|
5976
|
+
const { message, stack } = error2;
|
|
5977
|
+
if (message === "Load failed") {
|
|
5978
|
+
return stack === void 0 || "__sentry_captured__" in error2;
|
|
5979
|
+
}
|
|
5980
|
+
if (message.startsWith("error sending request for url")) {
|
|
5981
|
+
return true;
|
|
5982
|
+
}
|
|
5983
|
+
if (message === "Failed to fetch" || message.startsWith("Failed to fetch (") && message.endsWith(")")) {
|
|
5984
|
+
return true;
|
|
5985
|
+
}
|
|
5986
|
+
return errorMessages.has(message);
|
|
5987
|
+
}
|
|
5988
|
+
|
|
5989
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/utils/type-guards.js
|
|
5990
|
+
var isErrorType = (error2, cls) => error2 instanceof cls || error2?.name === cls.name;
|
|
5865
5991
|
function isHTTPError(error2) {
|
|
5866
|
-
return error2
|
|
5992
|
+
return isErrorType(error2, HTTPError);
|
|
5993
|
+
}
|
|
5994
|
+
function isNetworkError(error2) {
|
|
5995
|
+
return isErrorType(error2, NetworkError);
|
|
5867
5996
|
}
|
|
5868
5997
|
function isTimeoutError(error2) {
|
|
5869
|
-
return error2
|
|
5998
|
+
return isErrorType(error2, TimeoutError);
|
|
5870
5999
|
}
|
|
5871
6000
|
|
|
5872
|
-
// ../../node_modules/.pnpm/ky@
|
|
6001
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/core/Ky.js
|
|
6002
|
+
var maxErrorResponseBodySize = 10 * 1024 * 1024;
|
|
6003
|
+
var prefixUrlRenamedErrorMessage = "The `prefixUrl` option has been renamed `prefix` in v2 and enhanced to allow slashes in input. See also the new `baseUrl` option for improved flexibility with standard URL resolution: https://github.com/sindresorhus/ky#baseurl";
|
|
6004
|
+
var timedOutResponseData = /* @__PURE__ */ Symbol("timedOutResponseData");
|
|
6005
|
+
var createTextDecoder = (contentType) => {
|
|
6006
|
+
const match = /;\s*charset\s*=\s*(?:"([^"]+)"|([^;,\s]+))/i.exec(contentType);
|
|
6007
|
+
const charset = match?.[1] ?? match?.[2];
|
|
6008
|
+
if (charset) {
|
|
6009
|
+
try {
|
|
6010
|
+
return new TextDecoder(charset);
|
|
6011
|
+
} catch {
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
return new TextDecoder();
|
|
6015
|
+
};
|
|
6016
|
+
var invalidSchemaMessage = "The `schema` argument must follow the Standard Schema specification";
|
|
6017
|
+
var cloneRetryOptions = (retry2) => {
|
|
6018
|
+
if (typeof retry2 !== "object") {
|
|
6019
|
+
return retry2;
|
|
6020
|
+
}
|
|
6021
|
+
return {
|
|
6022
|
+
...retry2,
|
|
6023
|
+
...retry2.methods && { methods: [...retry2.methods] },
|
|
6024
|
+
...retry2.statusCodes && { statusCodes: [...retry2.statusCodes] },
|
|
6025
|
+
...retry2.afterStatusCodes && { afterStatusCodes: [...retry2.afterStatusCodes] }
|
|
6026
|
+
};
|
|
6027
|
+
};
|
|
6028
|
+
var objectToString2 = Object.prototype.toString;
|
|
6029
|
+
var isRequestInstance = (value) => value instanceof globalThis.Request || objectToString2.call(value) === "[object Request]";
|
|
6030
|
+
var isResponseInstance = (value) => value instanceof globalThis.Response || objectToString2.call(value) === "[object Response]";
|
|
6031
|
+
var cloneSearchParametersForInitHook = (searchParameters) => {
|
|
6032
|
+
if (Array.isArray(searchParameters)) {
|
|
6033
|
+
return searchParameters.map((parameter) => [...parameter]);
|
|
6034
|
+
}
|
|
6035
|
+
return cloneShallow(searchParameters);
|
|
6036
|
+
};
|
|
6037
|
+
function cloneInitHookOptions(options) {
|
|
6038
|
+
const clonedOptions = {
|
|
6039
|
+
...options,
|
|
6040
|
+
json: cloneShallow(options.json),
|
|
6041
|
+
context: cloneShallow(options.context),
|
|
6042
|
+
headers: cloneShallow(options.headers),
|
|
6043
|
+
searchParams: cloneSearchParametersForInitHook(options.searchParams)
|
|
6044
|
+
};
|
|
6045
|
+
if (options.retry !== void 0) {
|
|
6046
|
+
clonedOptions.retry = cloneRetryOptions(options.retry);
|
|
6047
|
+
}
|
|
6048
|
+
return clonedOptions;
|
|
6049
|
+
}
|
|
6050
|
+
var validateJsonWithSchema = async (jsonValue, schema) => {
|
|
6051
|
+
if (typeof schema !== "object" && typeof schema !== "function" || schema === null) {
|
|
6052
|
+
throw new TypeError(invalidSchemaMessage);
|
|
6053
|
+
}
|
|
6054
|
+
const standardSchema = schema["~standard"];
|
|
6055
|
+
if (typeof standardSchema !== "object" || standardSchema === null || typeof standardSchema.validate !== "function") {
|
|
6056
|
+
throw new TypeError(invalidSchemaMessage);
|
|
6057
|
+
}
|
|
6058
|
+
const validationResult = await standardSchema.validate(jsonValue);
|
|
6059
|
+
if (validationResult.issues) {
|
|
6060
|
+
throw new SchemaValidationError(validationResult.issues);
|
|
6061
|
+
}
|
|
6062
|
+
return validationResult.value;
|
|
6063
|
+
};
|
|
5873
6064
|
var Ky = class _Ky {
|
|
5874
6065
|
static create(input, options) {
|
|
5875
|
-
const
|
|
6066
|
+
const initHooks = options.hooks?.init ?? [];
|
|
6067
|
+
const initHookOptions = initHooks.length > 0 ? cloneInitHookOptions(options) : options;
|
|
6068
|
+
for (const hook of initHooks) {
|
|
6069
|
+
hook(initHookOptions);
|
|
6070
|
+
}
|
|
6071
|
+
const ky2 = new _Ky(input, initHookOptions);
|
|
5876
6072
|
const function_ = async () => {
|
|
5877
6073
|
if (typeof ky2.#options.timeout === "number" && ky2.#options.timeout > maxSafeTimeout) {
|
|
5878
6074
|
throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
|
|
5879
6075
|
}
|
|
6076
|
+
if (typeof ky2.#options.totalTimeout === "number" && ky2.#options.totalTimeout > maxSafeTimeout) {
|
|
6077
|
+
throw new RangeError(`The \`totalTimeout\` option cannot be greater than ${maxSafeTimeout}`);
|
|
6078
|
+
}
|
|
5880
6079
|
await Promise.resolve();
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
}
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
6080
|
+
const beforeRequestResponse = await ky2.#runBeforeRequestHooks();
|
|
6081
|
+
let response = beforeRequestResponse ?? await ky2.#retry(async () => ky2.#fetch());
|
|
6082
|
+
let responseFromHook = beforeRequestResponse !== void 0 || ky2.#consumeReturnedResponseFromBeforeRetryHook();
|
|
6083
|
+
for (; ; ) {
|
|
6084
|
+
if (response === void 0) {
|
|
6085
|
+
return response;
|
|
6086
|
+
}
|
|
6087
|
+
if (isResponseInstance(response)) {
|
|
6088
|
+
try {
|
|
6089
|
+
response = await ky2.#runAfterResponseHooks(response);
|
|
6090
|
+
} catch (error2) {
|
|
6091
|
+
if (!(error2 instanceof ForceRetryError)) {
|
|
6092
|
+
throw error2;
|
|
6093
|
+
}
|
|
6094
|
+
const retriedResponse = await ky2.#retryFromError(error2, async () => ky2.#fetch());
|
|
6095
|
+
if (retriedResponse === void 0) {
|
|
6096
|
+
return retriedResponse;
|
|
6097
|
+
}
|
|
6098
|
+
response = retriedResponse;
|
|
6099
|
+
responseFromHook = ky2.#consumeReturnedResponseFromBeforeRetryHook();
|
|
6100
|
+
continue;
|
|
6101
|
+
}
|
|
5900
6102
|
}
|
|
5901
|
-
|
|
5902
|
-
|
|
6103
|
+
const currentResponse = response;
|
|
6104
|
+
if (!currentResponse.ok && currentResponse.type !== "opaque" && (typeof ky2.#options.throwHttpErrors === "function" ? ky2.#options.throwHttpErrors(currentResponse.status) : ky2.#options.throwHttpErrors)) {
|
|
6105
|
+
const httpError = new HTTPError(currentResponse, ky2.#getResponseRequest(currentResponse), ky2.#getNormalizedOptions());
|
|
6106
|
+
const errorToThrow = httpError;
|
|
6107
|
+
httpError.data = await ky2.#getResponseData(currentResponse);
|
|
6108
|
+
if (responseFromHook) {
|
|
6109
|
+
throw errorToThrow;
|
|
6110
|
+
}
|
|
6111
|
+
const retriedResponse = await ky2.#retryFromError(httpError, async () => ky2.#fetch());
|
|
6112
|
+
if (retriedResponse === void 0) {
|
|
6113
|
+
return retriedResponse;
|
|
6114
|
+
}
|
|
6115
|
+
response = retriedResponse;
|
|
6116
|
+
responseFromHook = ky2.#consumeReturnedResponseFromBeforeRetryHook();
|
|
6117
|
+
continue;
|
|
5903
6118
|
}
|
|
5904
|
-
|
|
6119
|
+
break;
|
|
5905
6120
|
}
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
let error2 = new HTTPError(response, ky2.request, ky2.#getNormalizedOptions());
|
|
5909
|
-
for (const hook of ky2.#options.hooks.beforeError) {
|
|
5910
|
-
error2 = await hook(error2, { retryCount: ky2.#retryCount });
|
|
5911
|
-
}
|
|
5912
|
-
throw error2;
|
|
6121
|
+
if (!isResponseInstance(response)) {
|
|
6122
|
+
return response;
|
|
5913
6123
|
}
|
|
6124
|
+
ky2.#decorateResponse(response);
|
|
5914
6125
|
if (ky2.#options.onDownloadProgress) {
|
|
5915
6126
|
if (typeof ky2.#options.onDownloadProgress !== "function") {
|
|
5916
6127
|
throw new TypeError("The `onDownloadProgress` option must be a function");
|
|
@@ -5924,32 +6135,56 @@ var Ky = class _Ky {
|
|
|
5924
6135
|
}
|
|
5925
6136
|
return response;
|
|
5926
6137
|
};
|
|
5927
|
-
const result =
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
6138
|
+
const result = (async () => {
|
|
6139
|
+
try {
|
|
6140
|
+
return await function_();
|
|
6141
|
+
} catch (error2) {
|
|
6142
|
+
if (!(error2 instanceof Error)) {
|
|
6143
|
+
throw error2;
|
|
6144
|
+
}
|
|
6145
|
+
if (ky2.#beforeRetryHookErrors.has(error2)) {
|
|
6146
|
+
throw error2;
|
|
6147
|
+
}
|
|
6148
|
+
let processedError = error2;
|
|
6149
|
+
for (const hook of ky2.#options.hooks.beforeError) {
|
|
6150
|
+
const hookResult = await hook({
|
|
6151
|
+
request: ky2.request,
|
|
6152
|
+
options: ky2.#getNormalizedOptions(),
|
|
6153
|
+
error: processedError,
|
|
6154
|
+
retryCount: ky2.#retryCount
|
|
6155
|
+
});
|
|
6156
|
+
if (hookResult instanceof Error) {
|
|
6157
|
+
processedError = hookResult;
|
|
6158
|
+
}
|
|
6159
|
+
}
|
|
6160
|
+
throw processedError;
|
|
6161
|
+
} finally {
|
|
6162
|
+
const originalRequest = ky2.#originalRequest;
|
|
6163
|
+
ky2.#cancelBody(originalRequest?.body ?? void 0);
|
|
6164
|
+
if (ky2.request !== originalRequest) {
|
|
6165
|
+
ky2.#cancelBody(ky2.request.body ?? void 0);
|
|
6166
|
+
}
|
|
6167
|
+
}
|
|
6168
|
+
})();
|
|
5932
6169
|
for (const [type, mimeType] of Object.entries(responseTypes)) {
|
|
5933
6170
|
if (type === "bytes" && typeof globalThis.Response?.prototype?.bytes !== "function") {
|
|
5934
6171
|
continue;
|
|
5935
6172
|
}
|
|
5936
|
-
result[type] = async () => {
|
|
6173
|
+
result[type] = async (schema) => {
|
|
5937
6174
|
ky2.request.headers.set("accept", ky2.request.headers.get("accept") || mimeType);
|
|
5938
6175
|
const response = await result;
|
|
5939
|
-
if (type
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
if (
|
|
5945
|
-
return
|
|
5946
|
-
}
|
|
5947
|
-
if (options.parseJson) {
|
|
5948
|
-
return options.parseJson(text);
|
|
6176
|
+
if (type !== "json") {
|
|
6177
|
+
return response[type]();
|
|
6178
|
+
}
|
|
6179
|
+
const text = await response.text();
|
|
6180
|
+
if (text === "") {
|
|
6181
|
+
if (schema !== void 0) {
|
|
6182
|
+
return validateJsonWithSchema(void 0, schema);
|
|
5949
6183
|
}
|
|
5950
6184
|
return JSON.parse(text);
|
|
5951
6185
|
}
|
|
5952
|
-
|
|
6186
|
+
const jsonValue = initHookOptions.parseJson ? await initHookOptions.parseJson(text, { request: ky2.#getResponseRequest(response), response }) : JSON.parse(text);
|
|
6187
|
+
return schema === void 0 ? jsonValue : validateJsonWithSchema(jsonValue, schema);
|
|
5953
6188
|
};
|
|
5954
6189
|
}
|
|
5955
6190
|
return result;
|
|
@@ -5969,44 +6204,55 @@ var Ky = class _Ky {
|
|
|
5969
6204
|
#options;
|
|
5970
6205
|
#originalRequest;
|
|
5971
6206
|
#userProvidedAbortSignal;
|
|
6207
|
+
#beforeRetryHookErrors = /* @__PURE__ */ new WeakSet();
|
|
5972
6208
|
#cachedNormalizedOptions;
|
|
6209
|
+
#startTime;
|
|
6210
|
+
#returnedResponseFromBeforeRetryHook = false;
|
|
6211
|
+
#responseRequests = /* @__PURE__ */ new WeakMap();
|
|
5973
6212
|
// eslint-disable-next-line complexity
|
|
5974
6213
|
constructor(input, options = {}) {
|
|
5975
6214
|
this.#input = input;
|
|
6215
|
+
if (Object.hasOwn(options, "prefixUrl")) {
|
|
6216
|
+
throw new Error(prefixUrlRenamedErrorMessage);
|
|
6217
|
+
}
|
|
5976
6218
|
this.#options = {
|
|
5977
6219
|
...options,
|
|
5978
6220
|
headers: mergeHeaders(this.#input.headers, options.headers),
|
|
5979
|
-
hooks: mergeHooks({
|
|
5980
|
-
beforeRequest: [],
|
|
5981
|
-
beforeRetry: [],
|
|
5982
|
-
beforeError: [],
|
|
5983
|
-
afterResponse: []
|
|
5984
|
-
}, options.hooks),
|
|
6221
|
+
hooks: mergeHooks({}, options.hooks),
|
|
5985
6222
|
method: normalizeRequestMethod(options.method ?? this.#input.method ?? "GET"),
|
|
5986
6223
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
5987
|
-
|
|
6224
|
+
prefix: String(options.prefix || ""),
|
|
5988
6225
|
retry: normalizeRetryOptions(options.retry),
|
|
5989
6226
|
throwHttpErrors: options.throwHttpErrors ?? true,
|
|
5990
6227
|
timeout: options.timeout ?? 1e4,
|
|
6228
|
+
totalTimeout: options.totalTimeout ?? false,
|
|
5991
6229
|
fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
|
|
5992
6230
|
context: options.context ?? {}
|
|
5993
6231
|
};
|
|
5994
6232
|
if (typeof this.#input !== "string" && !(this.#input instanceof URL || this.#input instanceof globalThis.Request)) {
|
|
5995
6233
|
throw new TypeError("`input` must be a string, URL, or Request");
|
|
5996
6234
|
}
|
|
5997
|
-
if (
|
|
5998
|
-
if (this.#
|
|
5999
|
-
|
|
6235
|
+
if (typeof this.#input === "string") {
|
|
6236
|
+
if (this.#options.prefix) {
|
|
6237
|
+
const normalizedPrefix = this.#options.prefix.replace(/\/+$/, "");
|
|
6238
|
+
const normalizedInput = this.#input.replace(/^\/+/, "");
|
|
6239
|
+
this.#input = `${normalizedPrefix}/${normalizedInput}`;
|
|
6000
6240
|
}
|
|
6001
|
-
if (
|
|
6002
|
-
|
|
6241
|
+
if (this.#options.baseUrl) {
|
|
6242
|
+
let absoluteInput;
|
|
6243
|
+
try {
|
|
6244
|
+
absoluteInput = new URL(this.#input);
|
|
6245
|
+
} catch {
|
|
6246
|
+
}
|
|
6247
|
+
if (!absoluteInput) {
|
|
6248
|
+
this.#input = new URL(this.#input, new Request(this.#options.baseUrl).url);
|
|
6249
|
+
}
|
|
6003
6250
|
}
|
|
6004
|
-
this.#input = this.#options.prefixUrl + this.#input;
|
|
6005
6251
|
}
|
|
6006
6252
|
if (supportsAbortController && supportsAbortSignal) {
|
|
6007
6253
|
this.#userProvidedAbortSignal = this.#options.signal ?? this.#input.signal;
|
|
6008
6254
|
this.#abortController = new globalThis.AbortController();
|
|
6009
|
-
this.#options.signal = this.#
|
|
6255
|
+
this.#options.signal = this.#createManagedSignal();
|
|
6010
6256
|
}
|
|
6011
6257
|
if (supportsRequestStreams) {
|
|
6012
6258
|
this.#options.duplex = "half";
|
|
@@ -6021,23 +6267,40 @@ var Ky = class _Ky {
|
|
|
6021
6267
|
}
|
|
6022
6268
|
this.request = new globalThis.Request(this.#input, this.#options);
|
|
6023
6269
|
if (hasSearchParameters(this.#options.searchParams)) {
|
|
6024
|
-
const
|
|
6025
|
-
const
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
if (typeof this.#options.onUploadProgress !== "function") {
|
|
6031
|
-
throw new TypeError("The `onUploadProgress` option must be a function");
|
|
6270
|
+
const url = new URL(this.request.url);
|
|
6271
|
+
const deleted = this.#options.searchParams?.[deletedParametersSymbol];
|
|
6272
|
+
if (deleted) {
|
|
6273
|
+
for (const key of deleted) {
|
|
6274
|
+
url.searchParams.delete(key);
|
|
6275
|
+
}
|
|
6032
6276
|
}
|
|
6033
|
-
if (
|
|
6034
|
-
|
|
6277
|
+
if (typeof this.#options.searchParams === "string") {
|
|
6278
|
+
const stringSearchParameters = this.#options.searchParams.replace(/^\?/, "");
|
|
6279
|
+
if (stringSearchParameters !== "") {
|
|
6280
|
+
url.search = url.search ? `${url.search}&${stringSearchParameters}` : `?${stringSearchParameters}`;
|
|
6281
|
+
}
|
|
6282
|
+
} else {
|
|
6283
|
+
const optionsSearchParameters = new URLSearchParams(_Ky.#normalizeSearchParams(this.#options.searchParams));
|
|
6284
|
+
for (const [key, value] of optionsSearchParameters.entries()) {
|
|
6285
|
+
url.searchParams.append(key, value);
|
|
6286
|
+
}
|
|
6035
6287
|
}
|
|
6036
|
-
this.
|
|
6288
|
+
if (this.#options.searchParams && typeof this.#options.searchParams === "object" && !Array.isArray(this.#options.searchParams) && !(this.#options.searchParams instanceof URLSearchParams)) {
|
|
6289
|
+
for (const [key, value] of Object.entries(this.#options.searchParams)) {
|
|
6290
|
+
if (value === void 0) {
|
|
6291
|
+
url.searchParams.delete(key);
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
}
|
|
6295
|
+
this.request = new globalThis.Request(url, this.#options);
|
|
6296
|
+
}
|
|
6297
|
+
if (this.#options.onUploadProgress && typeof this.#options.onUploadProgress !== "function") {
|
|
6298
|
+
throw new TypeError("The `onUploadProgress` option must be a function");
|
|
6037
6299
|
}
|
|
6300
|
+
this.#startTime = typeof this.#options.totalTimeout === "number" ? this.#getCurrentTime() : void 0;
|
|
6038
6301
|
}
|
|
6039
6302
|
#calculateDelay() {
|
|
6040
|
-
const retryDelay = this.#options.retry.delay(this.#retryCount);
|
|
6303
|
+
const retryDelay = this.#options.retry.delay(this.#retryCount + 1);
|
|
6041
6304
|
let jitteredDelay = retryDelay;
|
|
6042
6305
|
if (this.#options.retry.jitter === true) {
|
|
6043
6306
|
jitteredDelay = Math.random() * retryDelay;
|
|
@@ -6047,12 +6310,10 @@ var Ky = class _Ky {
|
|
|
6047
6310
|
jitteredDelay = retryDelay;
|
|
6048
6311
|
}
|
|
6049
6312
|
}
|
|
6050
|
-
|
|
6051
|
-
return Math.min(backoffLimit, jitteredDelay);
|
|
6313
|
+
return Math.min(this.#options.retry.backoffLimit, jitteredDelay);
|
|
6052
6314
|
}
|
|
6053
6315
|
async #calculateRetryDelay(error2) {
|
|
6054
|
-
this.#retryCount
|
|
6055
|
-
if (this.#retryCount > this.#options.retry.limit) {
|
|
6316
|
+
if (this.#retryCount >= this.#options.retry.limit) {
|
|
6056
6317
|
throw error2;
|
|
6057
6318
|
}
|
|
6058
6319
|
const errorObject = error2 instanceof Error ? error2 : new NonError(error2);
|
|
@@ -6063,7 +6324,7 @@ var Ky = class _Ky {
|
|
|
6063
6324
|
throw error2;
|
|
6064
6325
|
}
|
|
6065
6326
|
if (this.#options.retry.shouldRetry !== void 0) {
|
|
6066
|
-
const result = await this.#options.retry.shouldRetry({ error: errorObject, retryCount: this.#retryCount });
|
|
6327
|
+
const result = await this.#options.retry.shouldRetry({ error: errorObject, retryCount: this.#retryCount + 1 });
|
|
6067
6328
|
if (result === false) {
|
|
6068
6329
|
throw error2;
|
|
6069
6330
|
}
|
|
@@ -6071,8 +6332,11 @@ var Ky = class _Ky {
|
|
|
6071
6332
|
return this.#calculateDelay();
|
|
6072
6333
|
}
|
|
6073
6334
|
}
|
|
6074
|
-
if (isTimeoutError(error2)
|
|
6075
|
-
|
|
6335
|
+
if (isTimeoutError(error2)) {
|
|
6336
|
+
if (!this.#options.retry.retryOnTimeout) {
|
|
6337
|
+
throw error2;
|
|
6338
|
+
}
|
|
6339
|
+
return this.#calculateDelay();
|
|
6076
6340
|
}
|
|
6077
6341
|
if (isHTTPError(error2)) {
|
|
6078
6342
|
if (!this.#options.retry.statusCodes.includes(error2.response.status)) {
|
|
@@ -6086,21 +6350,138 @@ var Ky = class _Ky {
|
|
|
6086
6350
|
} else if (after >= Date.parse("2024-01-01")) {
|
|
6087
6351
|
after -= Date.now();
|
|
6088
6352
|
}
|
|
6089
|
-
|
|
6090
|
-
|
|
6353
|
+
if (!Number.isFinite(after)) {
|
|
6354
|
+
return Math.min(this.#options.retry.maxRetryAfter, this.#calculateDelay());
|
|
6355
|
+
}
|
|
6356
|
+
after = Math.max(0, after);
|
|
6357
|
+
return Math.min(this.#options.retry.maxRetryAfter, after);
|
|
6091
6358
|
}
|
|
6092
6359
|
if (error2.response.status === 413) {
|
|
6093
6360
|
throw error2;
|
|
6094
6361
|
}
|
|
6362
|
+
return this.#calculateDelay();
|
|
6363
|
+
}
|
|
6364
|
+
if (!isNetworkError(error2)) {
|
|
6365
|
+
throw error2;
|
|
6095
6366
|
}
|
|
6096
6367
|
return this.#calculateDelay();
|
|
6097
6368
|
}
|
|
6098
6369
|
#decorateResponse(response) {
|
|
6370
|
+
const request = this.#getResponseRequest(response);
|
|
6099
6371
|
if (this.#options.parseJson) {
|
|
6100
|
-
response.json = async () =>
|
|
6372
|
+
response.json = async () => {
|
|
6373
|
+
const text = await response.text();
|
|
6374
|
+
if (text === "") {
|
|
6375
|
+
return JSON.parse(text);
|
|
6376
|
+
}
|
|
6377
|
+
return this.#options.parseJson(text, { request, response });
|
|
6378
|
+
};
|
|
6101
6379
|
}
|
|
6102
6380
|
return response;
|
|
6103
6381
|
}
|
|
6382
|
+
async #getResponseData(response) {
|
|
6383
|
+
const text = await this.#readResponseText(response, this.#getErrorDataTimeout());
|
|
6384
|
+
if (text === timedOutResponseData) {
|
|
6385
|
+
this.#throwIfTotalTimeoutExhausted();
|
|
6386
|
+
return void 0;
|
|
6387
|
+
}
|
|
6388
|
+
if (!text) {
|
|
6389
|
+
return void 0;
|
|
6390
|
+
}
|
|
6391
|
+
if (!this.#isJsonContentType(response.headers.get("content-type") ?? "")) {
|
|
6392
|
+
return text;
|
|
6393
|
+
}
|
|
6394
|
+
const data = await this.#parseJson(text, response, this.#getErrorDataTimeout(), this.#getResponseRequest(response));
|
|
6395
|
+
if (data === timedOutResponseData) {
|
|
6396
|
+
this.#throwIfTotalTimeoutExhausted();
|
|
6397
|
+
return void 0;
|
|
6398
|
+
}
|
|
6399
|
+
return data;
|
|
6400
|
+
}
|
|
6401
|
+
#getErrorDataTimeout() {
|
|
6402
|
+
const errorDataTimeout = this.#options.timeout === false ? 1e4 : this.#options.timeout;
|
|
6403
|
+
const remainingTotal = this.#getRemainingTotalTimeout();
|
|
6404
|
+
if (remainingTotal === void 0) {
|
|
6405
|
+
return errorDataTimeout;
|
|
6406
|
+
}
|
|
6407
|
+
if (remainingTotal <= 0) {
|
|
6408
|
+
throw new TimeoutError(this.request);
|
|
6409
|
+
}
|
|
6410
|
+
return Math.min(errorDataTimeout, remainingTotal);
|
|
6411
|
+
}
|
|
6412
|
+
#isJsonContentType(contentType) {
|
|
6413
|
+
const mimeType = (contentType.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
6414
|
+
return /\/(?:.*[.+-])?json$/.test(mimeType);
|
|
6415
|
+
}
|
|
6416
|
+
async #readResponseText(response, timeoutMs) {
|
|
6417
|
+
const { body } = response;
|
|
6418
|
+
if (!body) {
|
|
6419
|
+
try {
|
|
6420
|
+
return await response.text();
|
|
6421
|
+
} catch {
|
|
6422
|
+
return void 0;
|
|
6423
|
+
}
|
|
6424
|
+
}
|
|
6425
|
+
let reader;
|
|
6426
|
+
try {
|
|
6427
|
+
reader = body.getReader();
|
|
6428
|
+
} catch {
|
|
6429
|
+
return void 0;
|
|
6430
|
+
}
|
|
6431
|
+
const decoder = createTextDecoder(response.headers.get("content-type") ?? "");
|
|
6432
|
+
const chunks = [];
|
|
6433
|
+
let totalBytes = 0;
|
|
6434
|
+
const readAll = (async () => {
|
|
6435
|
+
try {
|
|
6436
|
+
for (; ; ) {
|
|
6437
|
+
const { done, value } = await reader.read();
|
|
6438
|
+
if (done) {
|
|
6439
|
+
break;
|
|
6440
|
+
}
|
|
6441
|
+
totalBytes += value.byteLength;
|
|
6442
|
+
if (totalBytes > maxErrorResponseBodySize) {
|
|
6443
|
+
void reader.cancel().catch(() => void 0);
|
|
6444
|
+
return void 0;
|
|
6445
|
+
}
|
|
6446
|
+
chunks.push(decoder.decode(value, { stream: true }));
|
|
6447
|
+
}
|
|
6448
|
+
} catch {
|
|
6449
|
+
return void 0;
|
|
6450
|
+
}
|
|
6451
|
+
chunks.push(decoder.decode());
|
|
6452
|
+
return chunks.join("");
|
|
6453
|
+
})();
|
|
6454
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
6455
|
+
const timeoutId = setTimeout(() => {
|
|
6456
|
+
resolve(timedOutResponseData);
|
|
6457
|
+
}, timeoutMs);
|
|
6458
|
+
void readAll.finally(() => {
|
|
6459
|
+
clearTimeout(timeoutId);
|
|
6460
|
+
});
|
|
6461
|
+
});
|
|
6462
|
+
const result = await Promise.race([readAll, timeoutPromise]);
|
|
6463
|
+
if (result === timedOutResponseData) {
|
|
6464
|
+
void reader.cancel().catch(() => void 0);
|
|
6465
|
+
}
|
|
6466
|
+
return result;
|
|
6467
|
+
}
|
|
6468
|
+
async #parseJson(text, response, timeoutMs, request) {
|
|
6469
|
+
let timeoutId;
|
|
6470
|
+
try {
|
|
6471
|
+
return await Promise.race([
|
|
6472
|
+
Promise.resolve().then(() => this.#options.parseJson ? this.#options.parseJson(text, { request, response }) : JSON.parse(text)),
|
|
6473
|
+
new Promise((resolve) => {
|
|
6474
|
+
timeoutId = setTimeout(() => {
|
|
6475
|
+
resolve(timedOutResponseData);
|
|
6476
|
+
}, timeoutMs);
|
|
6477
|
+
})
|
|
6478
|
+
]);
|
|
6479
|
+
} catch {
|
|
6480
|
+
return void 0;
|
|
6481
|
+
} finally {
|
|
6482
|
+
clearTimeout(timeoutId);
|
|
6483
|
+
}
|
|
6484
|
+
}
|
|
6104
6485
|
#cancelBody(body) {
|
|
6105
6486
|
if (!body) {
|
|
6106
6487
|
return;
|
|
@@ -6110,84 +6491,200 @@ var Ky = class _Ky {
|
|
|
6110
6491
|
#cancelResponseBody(response) {
|
|
6111
6492
|
this.#cancelBody(response.body ?? void 0);
|
|
6112
6493
|
}
|
|
6494
|
+
#createManagedSignal() {
|
|
6495
|
+
return this.#userProvidedAbortSignal ? AbortSignal.any([this.#userProvidedAbortSignal, this.#abortController.signal]) : this.#abortController.signal;
|
|
6496
|
+
}
|
|
6497
|
+
#throwIfTotalTimeoutExhausted() {
|
|
6498
|
+
const remaining = this.#getRemainingTotalTimeout();
|
|
6499
|
+
if (remaining !== void 0 && remaining <= 0) {
|
|
6500
|
+
throw new TimeoutError(this.request);
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
async #runBeforeRequestHooks() {
|
|
6504
|
+
for (const hook of this.#options.hooks.beforeRequest) {
|
|
6505
|
+
const result = await hook({
|
|
6506
|
+
request: this.request,
|
|
6507
|
+
options: this.#getNormalizedOptions(),
|
|
6508
|
+
retryCount: 0
|
|
6509
|
+
});
|
|
6510
|
+
if (isRequestInstance(result)) {
|
|
6511
|
+
this.#assignRequest(result);
|
|
6512
|
+
} else if (isResponseInstance(result)) {
|
|
6513
|
+
return result;
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
return void 0;
|
|
6517
|
+
}
|
|
6518
|
+
async #runAfterResponseHooks(response) {
|
|
6519
|
+
const responseRequest = this.#getResponseRequest(response);
|
|
6520
|
+
for (const hook of this.#options.hooks.afterResponse) {
|
|
6521
|
+
const hookResponse = this.#setResponseRequest(response.clone(), responseRequest);
|
|
6522
|
+
this.#decorateResponse(hookResponse);
|
|
6523
|
+
let modifiedResponse;
|
|
6524
|
+
try {
|
|
6525
|
+
modifiedResponse = await hook({
|
|
6526
|
+
request: this.request,
|
|
6527
|
+
options: this.#getNormalizedOptions(),
|
|
6528
|
+
response: hookResponse,
|
|
6529
|
+
retryCount: this.#retryCount
|
|
6530
|
+
});
|
|
6531
|
+
} catch (error2) {
|
|
6532
|
+
if (hookResponse !== response) {
|
|
6533
|
+
this.#cancelResponseBody(hookResponse);
|
|
6534
|
+
}
|
|
6535
|
+
this.#cancelResponseBody(response);
|
|
6536
|
+
throw error2;
|
|
6537
|
+
}
|
|
6538
|
+
if (modifiedResponse instanceof RetryMarker) {
|
|
6539
|
+
if (hookResponse !== response) {
|
|
6540
|
+
this.#cancelResponseBody(hookResponse);
|
|
6541
|
+
}
|
|
6542
|
+
this.#cancelResponseBody(response);
|
|
6543
|
+
throw new ForceRetryError(modifiedResponse.options);
|
|
6544
|
+
}
|
|
6545
|
+
const nextResponse = isResponseInstance(modifiedResponse) ? this.#setResponseRequest(modifiedResponse, responseRequest) : response;
|
|
6546
|
+
if (hookResponse !== response && hookResponse !== nextResponse && hookResponse.body !== nextResponse.body) {
|
|
6547
|
+
this.#cancelResponseBody(hookResponse);
|
|
6548
|
+
}
|
|
6549
|
+
if (response !== nextResponse && response.body !== nextResponse.body) {
|
|
6550
|
+
this.#cancelResponseBody(response);
|
|
6551
|
+
}
|
|
6552
|
+
response = nextResponse;
|
|
6553
|
+
}
|
|
6554
|
+
return response;
|
|
6555
|
+
}
|
|
6113
6556
|
async #retry(function_) {
|
|
6114
6557
|
try {
|
|
6115
6558
|
return await function_();
|
|
6116
6559
|
} catch (error2) {
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6560
|
+
return this.#retryFromError(error2, function_);
|
|
6561
|
+
}
|
|
6562
|
+
}
|
|
6563
|
+
async #retryFromError(error2, function_) {
|
|
6564
|
+
this.#returnedResponseFromBeforeRetryHook = false;
|
|
6565
|
+
const retryDelay = Math.min(await this.#calculateRetryDelay(error2), maxSafeTimeout);
|
|
6566
|
+
const delayOptions = { signal: this.#userProvidedAbortSignal };
|
|
6567
|
+
const remainingTimeout = this.#getRemainingTotalTimeout();
|
|
6568
|
+
if (remainingTimeout !== void 0) {
|
|
6569
|
+
if (remainingTimeout <= 0) {
|
|
6570
|
+
throw new TimeoutError(this.request);
|
|
6120
6571
|
}
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
this.#assignRequest(managedRequest);
|
|
6572
|
+
if (retryDelay >= remainingTimeout) {
|
|
6573
|
+
await delay(remainingTimeout, delayOptions);
|
|
6574
|
+
throw new TimeoutError(this.request);
|
|
6125
6575
|
}
|
|
6126
|
-
|
|
6127
|
-
|
|
6576
|
+
}
|
|
6577
|
+
await delay(retryDelay, delayOptions);
|
|
6578
|
+
this.#throwIfTotalTimeoutExhausted();
|
|
6579
|
+
if (error2 instanceof ForceRetryError && error2.customRequest) {
|
|
6580
|
+
const customRequest = new globalThis.Request(error2.customRequest, this.#options.signal ? { signal: this.#options.signal } : void 0);
|
|
6581
|
+
this.#assignRequest(customRequest);
|
|
6582
|
+
}
|
|
6583
|
+
for (const hook of this.#options.hooks.beforeRetry) {
|
|
6584
|
+
let hookResult;
|
|
6585
|
+
try {
|
|
6586
|
+
hookResult = await hook({
|
|
6128
6587
|
request: this.request,
|
|
6129
6588
|
options: this.#getNormalizedOptions(),
|
|
6130
6589
|
error: error2,
|
|
6131
|
-
retryCount: this.#retryCount
|
|
6590
|
+
retryCount: this.#retryCount + 1
|
|
6132
6591
|
});
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
}
|
|
6137
|
-
if (hookResult instanceof globalThis.Response) {
|
|
6138
|
-
return hookResult;
|
|
6139
|
-
}
|
|
6140
|
-
if (hookResult === stop) {
|
|
6141
|
-
return;
|
|
6592
|
+
} catch (hookError) {
|
|
6593
|
+
if (hookError instanceof Error && hookError !== error2) {
|
|
6594
|
+
this.#beforeRetryHookErrors.add(hookError);
|
|
6142
6595
|
}
|
|
6596
|
+
throw hookError;
|
|
6597
|
+
}
|
|
6598
|
+
if (isRequestInstance(hookResult)) {
|
|
6599
|
+
this.#assignRequest(hookResult);
|
|
6600
|
+
break;
|
|
6601
|
+
}
|
|
6602
|
+
if (isResponseInstance(hookResult)) {
|
|
6603
|
+
this.#returnedResponseFromBeforeRetryHook = true;
|
|
6604
|
+
this.#retryCount++;
|
|
6605
|
+
return hookResult;
|
|
6606
|
+
}
|
|
6607
|
+
if (hookResult === stop) {
|
|
6608
|
+
return;
|
|
6143
6609
|
}
|
|
6144
|
-
return this.#retry(function_);
|
|
6145
6610
|
}
|
|
6611
|
+
this.#throwIfTotalTimeoutExhausted();
|
|
6612
|
+
this.#retryCount++;
|
|
6613
|
+
return this.#retry(function_);
|
|
6614
|
+
}
|
|
6615
|
+
#consumeReturnedResponseFromBeforeRetryHook() {
|
|
6616
|
+
const value = this.#returnedResponseFromBeforeRetryHook;
|
|
6617
|
+
this.#returnedResponseFromBeforeRetryHook = false;
|
|
6618
|
+
return value;
|
|
6146
6619
|
}
|
|
6147
6620
|
async #fetch() {
|
|
6148
6621
|
if (this.#abortController?.signal.aborted) {
|
|
6149
6622
|
this.#abortController = new globalThis.AbortController();
|
|
6150
|
-
this.#options.signal = this.#
|
|
6623
|
+
this.#options.signal = this.#createManagedSignal();
|
|
6151
6624
|
this.request = new globalThis.Request(this.request, { signal: this.#options.signal });
|
|
6152
6625
|
}
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6626
|
+
const nonRequestOptions = findUnknownOptions(this.#options);
|
|
6627
|
+
const retryRequest = this.#options.retry.limit > 0 ? this.request.clone() : void 0;
|
|
6628
|
+
const request = this.#wrapRequestWithUploadProgress(this.request, this.#options.body ?? void 0);
|
|
6629
|
+
this.#originalRequest = request;
|
|
6630
|
+
if (retryRequest) {
|
|
6631
|
+
this.request = retryRequest;
|
|
6632
|
+
}
|
|
6633
|
+
try {
|
|
6634
|
+
const remainingTotal = this.#getRemainingTotalTimeout();
|
|
6635
|
+
if (remainingTotal !== void 0 && remainingTotal <= 0) {
|
|
6636
|
+
throw new TimeoutError(this.request);
|
|
6637
|
+
}
|
|
6638
|
+
const effectiveTimeout = this.#options.timeout === false ? remainingTotal : remainingTotal === void 0 ? this.#options.timeout : Math.min(this.#options.timeout, remainingTotal);
|
|
6639
|
+
const response = effectiveTimeout === void 0 ? await this.#options.fetch(request, nonRequestOptions) : await timeout(request, nonRequestOptions, this.#abortController, {
|
|
6640
|
+
timeout: effectiveTimeout,
|
|
6641
|
+
fetch: this.#options.fetch
|
|
6642
|
+
});
|
|
6643
|
+
return this.#setResponseRequest(response, request);
|
|
6644
|
+
} catch (error2) {
|
|
6645
|
+
if (isRawNetworkError(error2)) {
|
|
6646
|
+
throw new NetworkError(this.request, { cause: error2 });
|
|
6161
6647
|
}
|
|
6648
|
+
throw error2;
|
|
6162
6649
|
}
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
this
|
|
6166
|
-
|
|
6167
|
-
return this.#options.fetch(this.#originalRequest, nonRequestOptions);
|
|
6650
|
+
}
|
|
6651
|
+
#getRemainingTotalTimeout() {
|
|
6652
|
+
if (this.#startTime === void 0) {
|
|
6653
|
+
return void 0;
|
|
6168
6654
|
}
|
|
6169
|
-
|
|
6655
|
+
const elapsed = this.#getCurrentTime() - this.#startTime;
|
|
6656
|
+
return Math.max(0, this.#options.totalTimeout - elapsed);
|
|
6657
|
+
}
|
|
6658
|
+
#getCurrentTime() {
|
|
6659
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
6170
6660
|
}
|
|
6171
6661
|
#getNormalizedOptions() {
|
|
6172
6662
|
if (!this.#cachedNormalizedOptions) {
|
|
6173
|
-
const { hooks, ...normalizedOptions } = this.#options;
|
|
6663
|
+
const { hooks, json, parseJson, stringifyJson, searchParams, timeout: timeout2, totalTimeout, throwHttpErrors, fetch: fetch2, ...normalizedOptions } = this.#options;
|
|
6174
6664
|
this.#cachedNormalizedOptions = Object.freeze(normalizedOptions);
|
|
6175
6665
|
}
|
|
6176
6666
|
return this.#cachedNormalizedOptions;
|
|
6177
6667
|
}
|
|
6178
6668
|
#assignRequest(request) {
|
|
6179
6669
|
this.#cachedNormalizedOptions = void 0;
|
|
6180
|
-
this.request =
|
|
6670
|
+
this.request = request;
|
|
6671
|
+
}
|
|
6672
|
+
#getResponseRequest(response) {
|
|
6673
|
+
return this.#responseRequests.get(response) ?? this.request;
|
|
6674
|
+
}
|
|
6675
|
+
#setResponseRequest(response, request) {
|
|
6676
|
+
this.#responseRequests.set(response, request);
|
|
6677
|
+
return response;
|
|
6181
6678
|
}
|
|
6182
6679
|
#wrapRequestWithUploadProgress(request, originalBody) {
|
|
6183
|
-
if (!this.#options.onUploadProgress || !request.body) {
|
|
6680
|
+
if (!this.#options.onUploadProgress || !request.body || !supportsRequestStreams) {
|
|
6184
6681
|
return request;
|
|
6185
6682
|
}
|
|
6186
6683
|
return streamRequest(request, this.#options.onUploadProgress, originalBody ?? this.#options.body ?? void 0);
|
|
6187
6684
|
}
|
|
6188
6685
|
};
|
|
6189
6686
|
|
|
6190
|
-
// ../../node_modules/.pnpm/ky@
|
|
6687
|
+
// ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/index.js
|
|
6191
6688
|
var createInstance = (defaults) => {
|
|
6192
6689
|
const ky2 = (input, options) => Ky.create(input, validateAndMerge(defaults, options));
|
|
6193
6690
|
for (const method of requestMethods) {
|
|
@@ -6294,13 +6791,13 @@ var KinoSecClient = class {
|
|
|
6294
6791
|
constructor(config) {
|
|
6295
6792
|
const prefixPathname = new URL(config.apiUrl).pathname.replace(/\/?$/, "/");
|
|
6296
6793
|
this.api = distribution_default.create({
|
|
6297
|
-
|
|
6794
|
+
prefix: config.apiUrl,
|
|
6298
6795
|
headers: {
|
|
6299
6796
|
"user-agent": config.userAgent ?? `kinosec/0.1.0 (${process.platform})`
|
|
6300
6797
|
},
|
|
6301
6798
|
hooks: {
|
|
6302
6799
|
beforeRequest: [
|
|
6303
|
-
(request) => {
|
|
6800
|
+
({ request }) => {
|
|
6304
6801
|
request.headers.set("authorization", `Bearer ${config.token}`);
|
|
6305
6802
|
const url = new URL(request.url);
|
|
6306
6803
|
const path = url.pathname.slice(prefixPathname.length - 1);
|
|
@@ -6313,15 +6810,9 @@ var KinoSecClient = class {
|
|
|
6313
6810
|
}
|
|
6314
6811
|
],
|
|
6315
6812
|
beforeError: [
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
try {
|
|
6320
|
-
body = await response.json();
|
|
6321
|
-
} catch {
|
|
6322
|
-
body = null;
|
|
6323
|
-
}
|
|
6324
|
-
throw parseApiError(body, response.status);
|
|
6813
|
+
({ error: error2 }) => {
|
|
6814
|
+
if (!isHTTPError(error2)) return error2;
|
|
6815
|
+
return parseApiError(error2.data, error2.response.status);
|
|
6325
6816
|
}
|
|
6326
6817
|
]
|
|
6327
6818
|
},
|
|
@@ -6495,6 +6986,117 @@ var AuditResource = class {
|
|
|
6495
6986
|
return this.api.get("v1/audit", { searchParams: buildSearchParams(params) }).json();
|
|
6496
6987
|
}
|
|
6497
6988
|
};
|
|
6989
|
+
var MULTI_LEVEL_TLDS = /* @__PURE__ */ new Set([
|
|
6990
|
+
"co.uk",
|
|
6991
|
+
"org.uk",
|
|
6992
|
+
"ac.uk",
|
|
6993
|
+
"me.uk",
|
|
6994
|
+
"com.au",
|
|
6995
|
+
"net.au",
|
|
6996
|
+
"org.au",
|
|
6997
|
+
"co.nz",
|
|
6998
|
+
"net.nz",
|
|
6999
|
+
"org.nz",
|
|
7000
|
+
"co.jp",
|
|
7001
|
+
"or.jp",
|
|
7002
|
+
"ne.jp",
|
|
7003
|
+
"co.kr",
|
|
7004
|
+
"or.kr",
|
|
7005
|
+
"co.za",
|
|
7006
|
+
"org.za",
|
|
7007
|
+
"web.za",
|
|
7008
|
+
"co.in",
|
|
7009
|
+
"net.in",
|
|
7010
|
+
"org.in",
|
|
7011
|
+
"co.id",
|
|
7012
|
+
"or.id",
|
|
7013
|
+
"com.br",
|
|
7014
|
+
"net.br",
|
|
7015
|
+
"org.br",
|
|
7016
|
+
"com.mx",
|
|
7017
|
+
"org.mx",
|
|
7018
|
+
"com.ar",
|
|
7019
|
+
"org.ar",
|
|
7020
|
+
"com.cn",
|
|
7021
|
+
"net.cn",
|
|
7022
|
+
"org.cn",
|
|
7023
|
+
"com.tw",
|
|
7024
|
+
"org.tw",
|
|
7025
|
+
"com.sg",
|
|
7026
|
+
"org.sg",
|
|
7027
|
+
"com.ph",
|
|
7028
|
+
"org.ph",
|
|
7029
|
+
"com.tr",
|
|
7030
|
+
"org.tr",
|
|
7031
|
+
"com.ng",
|
|
7032
|
+
"org.ng"
|
|
7033
|
+
]);
|
|
7034
|
+
var PUBLIC_HOSTING_SUFFIXES = /* @__PURE__ */ new Set([
|
|
7035
|
+
"github.io",
|
|
7036
|
+
"gitlab.io",
|
|
7037
|
+
"bitbucket.io",
|
|
7038
|
+
"vercel.app",
|
|
7039
|
+
"netlify.app",
|
|
7040
|
+
"netlify.com",
|
|
7041
|
+
"lovable.app",
|
|
7042
|
+
"lovableproject.com",
|
|
7043
|
+
"herokuapp.com",
|
|
7044
|
+
"appspot.com",
|
|
7045
|
+
"firebaseapp.com",
|
|
7046
|
+
"web.app",
|
|
7047
|
+
"azurewebsites.net",
|
|
7048
|
+
"cloudfront.net",
|
|
7049
|
+
"amazonaws.com",
|
|
7050
|
+
"replit.app",
|
|
7051
|
+
"repl.co",
|
|
7052
|
+
"readme.io",
|
|
7053
|
+
"readthedocs.io",
|
|
7054
|
+
"readthedocs.org",
|
|
7055
|
+
"statuspage.io",
|
|
7056
|
+
"uptimerobot.com",
|
|
7057
|
+
"myshopify.com",
|
|
7058
|
+
"webflow.io",
|
|
7059
|
+
"wixsite.com",
|
|
7060
|
+
"squarespace.com",
|
|
7061
|
+
"blogspot.com",
|
|
7062
|
+
"tumblr.com",
|
|
7063
|
+
"substack.com",
|
|
7064
|
+
"medium.com",
|
|
7065
|
+
"slack.com",
|
|
7066
|
+
"notion.site",
|
|
7067
|
+
"codesandbox.io",
|
|
7068
|
+
"stackblitz.io",
|
|
7069
|
+
"glitch.me",
|
|
7070
|
+
"ngrok.app",
|
|
7071
|
+
"ngrok.io",
|
|
7072
|
+
"ngrok-free.app"
|
|
7073
|
+
]);
|
|
7074
|
+
var IPV4_RE = /^\d{1,3}(\.\d{1,3}){3}$/;
|
|
7075
|
+
function normalize(value) {
|
|
7076
|
+
return value.replace(/:\d+$/, "").replace(/\.+$/, "").toLowerCase();
|
|
7077
|
+
}
|
|
7078
|
+
function detectAssetType(value) {
|
|
7079
|
+
const host = normalize(value);
|
|
7080
|
+
if (IPV4_RE.test(host) || host.includes(":")) {
|
|
7081
|
+
return "ip";
|
|
7082
|
+
}
|
|
7083
|
+
const labels = host.split(".");
|
|
7084
|
+
if (labels.length <= 1) return "domain";
|
|
7085
|
+
const tld2 = labels.slice(-2).join(".");
|
|
7086
|
+
const registrableLabels = MULTI_LEVEL_TLDS.has(tld2) ? 3 : 2;
|
|
7087
|
+
return labels.length > registrableLabels ? "subdomain" : "domain";
|
|
7088
|
+
}
|
|
7089
|
+
function deriveParentDomain(value) {
|
|
7090
|
+
const host = normalize(value);
|
|
7091
|
+
if (detectAssetType(host) !== "subdomain") return null;
|
|
7092
|
+
const labels = host.split(".");
|
|
7093
|
+
const tld2 = labels.slice(-2).join(".");
|
|
7094
|
+
const registrableLabels = MULTI_LEVEL_TLDS.has(tld2) ? 3 : 2;
|
|
7095
|
+
return labels.slice(-registrableLabels).join(".");
|
|
7096
|
+
}
|
|
7097
|
+
function isPublicSuffix(value) {
|
|
7098
|
+
return PUBLIC_HOSTING_SUFFIXES.has(normalize(value));
|
|
7099
|
+
}
|
|
6498
7100
|
|
|
6499
7101
|
// src/lib/output.ts
|
|
6500
7102
|
var import_cli_table3 = __toESM(require_cli_table3(), 1);
|
|
@@ -7446,12 +8048,8 @@ import { join as join2, dirname as dirname2 } from "path";
|
|
|
7446
8048
|
// src/lib/config.ts
|
|
7447
8049
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, openSync, writeSync, closeSync, unlinkSync, constants } from "fs";
|
|
7448
8050
|
import { join, dirname } from "path";
|
|
7449
|
-
import { homedir
|
|
8051
|
+
import { homedir } from "os";
|
|
7450
8052
|
function getConfigDir() {
|
|
7451
|
-
const p = platform();
|
|
7452
|
-
if (p === "win32") {
|
|
7453
|
-
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "kinosec");
|
|
7454
|
-
}
|
|
7455
8053
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
7456
8054
|
if (xdg) return join(xdg, "kinosec");
|
|
7457
8055
|
return join(homedir(), ".config", "kinosec");
|
|
@@ -7472,7 +8070,7 @@ function readJsonFile(path) {
|
|
|
7472
8070
|
function writeJsonFile(path, data, restrictPermissions = false) {
|
|
7473
8071
|
ensureDir(dirname(path));
|
|
7474
8072
|
const content = JSON.stringify(data, null, 2) + "\n";
|
|
7475
|
-
if (restrictPermissions
|
|
8073
|
+
if (restrictPermissions) {
|
|
7476
8074
|
const fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC, 384);
|
|
7477
8075
|
writeSync(fd, content);
|
|
7478
8076
|
closeSync(fd);
|
|
@@ -8101,7 +8699,7 @@ function isUnicodeSupported() {
|
|
|
8101
8699
|
return Boolean(env2.WT_SESSION) || Boolean(env2.TERMINUS_SUBLIME) || env2.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env2.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
8102
8700
|
}
|
|
8103
8701
|
|
|
8104
|
-
// ../../node_modules/.pnpm/ora@9.4.
|
|
8702
|
+
// ../../node_modules/.pnpm/ora@9.4.1/node_modules/ora/index.js
|
|
8105
8703
|
import process8 from "process";
|
|
8106
8704
|
import { stripVTControlCharacters } from "util";
|
|
8107
8705
|
|
|
@@ -10836,7 +11434,7 @@ var StdinDiscarder = class {
|
|
|
10836
11434
|
var stdinDiscarder = new StdinDiscarder();
|
|
10837
11435
|
var stdin_discarder_default = Object.freeze(stdinDiscarder);
|
|
10838
11436
|
|
|
10839
|
-
// ../../node_modules/.pnpm/ora@9.4.
|
|
11437
|
+
// ../../node_modules/.pnpm/ora@9.4.1/node_modules/ora/index.js
|
|
10840
11438
|
var RENDER_DEFERRAL_TIMEOUT = 200;
|
|
10841
11439
|
var SYNCHRONIZED_OUTPUT_ENABLE = "\x1B[?2026h";
|
|
10842
11440
|
var SYNCHRONIZED_OUTPUT_DISABLE = "\x1B[?2026l";
|
|
@@ -11215,7 +11813,7 @@ var Ora = class {
|
|
|
11215
11813
|
return this;
|
|
11216
11814
|
}
|
|
11217
11815
|
start(text) {
|
|
11218
|
-
if (text) {
|
|
11816
|
+
if (text !== void 0) {
|
|
11219
11817
|
this.text = text;
|
|
11220
11818
|
}
|
|
11221
11819
|
if (this.isSilent) {
|
|
@@ -11417,10 +12015,9 @@ function extractPhase(entries) {
|
|
|
11417
12015
|
return null;
|
|
11418
12016
|
}
|
|
11419
12017
|
function printActivityLines(entries, tty3) {
|
|
11420
|
-
for (
|
|
11421
|
-
const
|
|
11422
|
-
const
|
|
11423
|
-
const text = tty3 ? isLastEntry ? import_picocolors5.default.green(entries[i]) : import_picocolors5.default.dim(import_picocolors5.default.green(entries[i])) : entries[i];
|
|
12018
|
+
for (const entry of entries) {
|
|
12019
|
+
const prompt = tty3 ? import_picocolors5.default.dim(import_picocolors5.default.green(">")) : ">";
|
|
12020
|
+
const text = tty3 ? import_picocolors5.default.dim(import_picocolors5.default.green(entry)) : entry;
|
|
11424
12021
|
console.log(`${prompt} ${text}`);
|
|
11425
12022
|
}
|
|
11426
12023
|
}
|
|
@@ -11447,7 +12044,7 @@ async function watchPentest(client, profileId, options) {
|
|
|
11447
12044
|
spinner.text = import_picocolors5.default.green(currentPhase ? `[${currentPhase}] ${buzz}...` : `${buzz}...`);
|
|
11448
12045
|
}
|
|
11449
12046
|
if (!useJson && tty3) {
|
|
11450
|
-
spinner = ora({ text: "Fetching pentest status...", color: "green", isEnabled: true }).start();
|
|
12047
|
+
spinner = ora({ text: "Fetching pentest status...", color: "green", isEnabled: true, discardStdin: false }).start();
|
|
11451
12048
|
cycler = createBuzzwordCycler(SCAN_EXECUTION_PHRASES, 2500, () => {
|
|
11452
12049
|
updateSpinnerText();
|
|
11453
12050
|
});
|
|
@@ -11462,71 +12059,134 @@ async function watchPentest(client, profileId, options) {
|
|
|
11462
12059
|
process.exit(0);
|
|
11463
12060
|
});
|
|
11464
12061
|
const showFullDetails = await resolveShowFullDetails(client);
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
12062
|
+
let consecutiveErrors = 0;
|
|
12063
|
+
const MAX_CONSECUTIVE_ERRORS = 2;
|
|
12064
|
+
let deferredExitCode = null;
|
|
12065
|
+
try {
|
|
12066
|
+
while (true) {
|
|
12067
|
+
let scanDetail;
|
|
12068
|
+
try {
|
|
12069
|
+
scanDetail = await client.scans.get(profileId);
|
|
12070
|
+
consecutiveErrors = 0;
|
|
12071
|
+
} catch (error2) {
|
|
12072
|
+
if (error2 instanceof ApiError) {
|
|
12073
|
+
if (error2.status === 401 || error2.status === 403) {
|
|
12074
|
+
throw error2;
|
|
12075
|
+
}
|
|
12076
|
+
if (error2.status === 404) {
|
|
12077
|
+
if (!useJson) {
|
|
12078
|
+
const icon2 = tty3 ? import_picocolors5.default.yellow(sym.warn) : sym.warn;
|
|
12079
|
+
console.log(`
|
|
12080
|
+
${icon2} Pentest is no longer available.`);
|
|
12081
|
+
console.log(` Check status: kinosec pentest get ${profileId}`);
|
|
12082
|
+
}
|
|
12083
|
+
break;
|
|
12084
|
+
}
|
|
12085
|
+
}
|
|
12086
|
+
consecutiveErrors++;
|
|
12087
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
12088
|
+
if (!useJson) {
|
|
12089
|
+
const icon2 = tty3 ? import_picocolors5.default.red(sym.fail) : sym.fail;
|
|
12090
|
+
console.log(`
|
|
12091
|
+
${icon2} Lost connection to pentest.`);
|
|
12092
|
+
console.log(` Check status: kinosec pentest get ${profileId}`);
|
|
12093
|
+
}
|
|
12094
|
+
break;
|
|
12095
|
+
}
|
|
12096
|
+
if (spinner) {
|
|
12097
|
+
spinner.text = import_picocolors5.default.yellow("Connection lost, retrying...");
|
|
12098
|
+
}
|
|
12099
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
12100
|
+
continue;
|
|
12101
|
+
}
|
|
12102
|
+
const totalMs = Date.now() - loopStart;
|
|
12103
|
+
if (useJson) {
|
|
12104
|
+
const elapsed = Math.round(totalMs / 1e3);
|
|
12105
|
+
process.stdout.write(
|
|
12106
|
+
JSON.stringify({ ...scanDetail, elapsed_seconds: elapsed }) + "\n"
|
|
12107
|
+
);
|
|
12108
|
+
} else {
|
|
12109
|
+
const normalized = normalizeActivityHistory(scanDetail.activity_history);
|
|
12110
|
+
const filtered = filterActivityForTier(normalized, showFullDetails);
|
|
12111
|
+
if (printedCount > filtered.length) printedCount = 0;
|
|
12112
|
+
const newEntries = filtered.slice(printedCount);
|
|
12113
|
+
if (newEntries.length > 0) {
|
|
12114
|
+
if (spinner) spinner.stop();
|
|
12115
|
+
printActivityLines(newEntries, tty3);
|
|
12116
|
+
printedCount += newEntries.length;
|
|
12117
|
+
if (spinner) spinner = ora({ color: "green", isEnabled: true, discardStdin: false }).start();
|
|
12118
|
+
}
|
|
12119
|
+
currentPhase = extractPhase(filtered);
|
|
12120
|
+
updateSpinnerText();
|
|
12121
|
+
}
|
|
12122
|
+
const status = scanDetail.scan_status;
|
|
12123
|
+
if (status === "Running...") {
|
|
12124
|
+
if (Date.now() - loopStart > timeoutMs) {
|
|
12125
|
+
const secs = Math.round(timeoutMs / 1e3);
|
|
12126
|
+
console.error(`
|
|
12127
|
+
Timeout: pentest still running after ${secs}s.`);
|
|
12128
|
+
console.error(`Check status: kinosec pentest get ${profileId}`);
|
|
12129
|
+
deferredExitCode = 3;
|
|
12130
|
+
break;
|
|
12131
|
+
}
|
|
12132
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
12133
|
+
continue;
|
|
12134
|
+
}
|
|
11490
12135
|
if (useJson) break;
|
|
11491
|
-
if (
|
|
12136
|
+
if (status === "Completed") {
|
|
12137
|
+
const totalDur = formatDuration(Date.now() - loopStart);
|
|
12138
|
+
const domain = tty3 ? import_picocolors5.default.bold(scanDetail.domain_or_ip) : scanDetail.domain_or_ip;
|
|
12139
|
+
const icon2 = tty3 ? import_picocolors5.default.green(sym.success) : sym.success;
|
|
12140
|
+
const dur = tty3 ? import_picocolors5.default.dim(totalDur) : totalDur;
|
|
12141
|
+
console.log(`
|
|
12142
|
+
${icon2} Pentest completed: ${domain} ${dur}`);
|
|
12143
|
+
if (showFindingsSummary) {
|
|
12144
|
+
await printFindingsSummary(client, profileId, tty3);
|
|
12145
|
+
}
|
|
12146
|
+
const cmd = `kinosec finding list ${profileId}`;
|
|
12147
|
+
const viewLabel = tty3 ? import_picocolors5.default.dim("View details:") : "View details:";
|
|
12148
|
+
const viewCmd = tty3 ? import_picocolors5.default.cyan(cmd) : cmd;
|
|
12149
|
+
console.log(`
|
|
12150
|
+
${viewLabel} ${viewCmd}`);
|
|
12151
|
+
console.log();
|
|
12152
|
+
break;
|
|
12153
|
+
}
|
|
12154
|
+
if (status === "Failed") {
|
|
11492
12155
|
const icon2 = tty3 ? import_picocolors5.default.red(sym.fail) : sym.fail;
|
|
11493
12156
|
const reason = scanDetail.failure_reason || "unknown reason";
|
|
11494
12157
|
console.log(`
|
|
11495
12158
|
${icon2} Pentest failed: ${reason}`);
|
|
11496
|
-
|
|
12159
|
+
deferredExitCode = 1;
|
|
12160
|
+
break;
|
|
11497
12161
|
}
|
|
11498
|
-
if (
|
|
12162
|
+
if (status === "Stopping...") {
|
|
11499
12163
|
const icon2 = tty3 ? import_picocolors5.default.yellow(sym.warn) : sym.warn;
|
|
11500
12164
|
console.log(`
|
|
11501
|
-
${icon2} Pentest
|
|
12165
|
+
${icon2} Pentest is being stopped.`);
|
|
11502
12166
|
break;
|
|
11503
12167
|
}
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
${icon} Pentest completed: ${domain} ${dur}`);
|
|
11510
|
-
if (showFindingsSummary) {
|
|
11511
|
-
await printFindingsSummary(client, profileId, tty3);
|
|
12168
|
+
if (status === "Not Yet Started") {
|
|
12169
|
+
const icon2 = tty3 ? import_picocolors5.default.yellow(sym.warn) : sym.warn;
|
|
12170
|
+
console.log(`
|
|
12171
|
+
${icon2} Pentest was stopped.`);
|
|
12172
|
+
break;
|
|
11512
12173
|
}
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
12174
|
+
if (status === "Scheduled") {
|
|
12175
|
+
const icon2 = tty3 ? import_picocolors5.default.yellow(sym.warn) : sym.warn;
|
|
12176
|
+
console.log(`
|
|
12177
|
+
${icon2} Pentest is scheduled, not currently running.`);
|
|
12178
|
+
break;
|
|
12179
|
+
}
|
|
12180
|
+
const icon = tty3 ? import_picocolors5.default.yellow(sym.warn) : sym.warn;
|
|
11516
12181
|
console.log(`
|
|
11517
|
-
|
|
11518
|
-
console.log();
|
|
12182
|
+
${icon} Unexpected status: ${status}`);
|
|
11519
12183
|
break;
|
|
11520
12184
|
}
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
console.error(`Check status: kinosec pentest get ${profileId}`);
|
|
11527
|
-
process.exit(3);
|
|
11528
|
-
}
|
|
11529
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
12185
|
+
} finally {
|
|
12186
|
+
cleanup();
|
|
12187
|
+
}
|
|
12188
|
+
if (deferredExitCode !== null) {
|
|
12189
|
+
process.exit(deferredExitCode);
|
|
11530
12190
|
}
|
|
11531
12191
|
}
|
|
11532
12192
|
async function printFindingsSummary(client, profileId, tty3) {
|
|
@@ -11763,6 +12423,15 @@ function validateScopeHosts(hosts) {
|
|
|
11763
12423
|
seen.add(lower);
|
|
11764
12424
|
}
|
|
11765
12425
|
}
|
|
12426
|
+
function validateScopeHostOwnership(hosts, assetValue) {
|
|
12427
|
+
const suffix = `.${assetValue.toLowerCase()}`;
|
|
12428
|
+
for (const host of hosts) {
|
|
12429
|
+
if (!host.toLowerCase().endsWith(suffix)) {
|
|
12430
|
+
console.error(`Error: ${host} is not a subdomain of ${assetValue}.`);
|
|
12431
|
+
process.exit(2);
|
|
12432
|
+
}
|
|
12433
|
+
}
|
|
12434
|
+
}
|
|
11766
12435
|
function validateScopeFlags(options) {
|
|
11767
12436
|
if (options.include && options.exclude) {
|
|
11768
12437
|
console.error("Error: --include and --exclude cannot be used together. Use one or the other.");
|
|
@@ -11857,15 +12526,45 @@ Existing ${existingMode} scope:`);
|
|
|
11857
12526
|
return { scope_filter: mode, scope_hosts: newHosts };
|
|
11858
12527
|
}
|
|
11859
12528
|
|
|
11860
|
-
// src/
|
|
11861
|
-
function
|
|
11862
|
-
const
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
12529
|
+
// src/lib/parse-target.ts
|
|
12530
|
+
function parseTarget(input) {
|
|
12531
|
+
const warnings = [];
|
|
12532
|
+
let value = input.trim();
|
|
12533
|
+
const protocolMatch = value.match(/^https?:\/\/(.+)/i);
|
|
12534
|
+
if (protocolMatch) {
|
|
12535
|
+
value = protocolMatch[1];
|
|
12536
|
+
}
|
|
12537
|
+
const slashIndex = value.indexOf("/");
|
|
12538
|
+
if (slashIndex !== -1) {
|
|
12539
|
+
value = value.slice(0, slashIndex);
|
|
12540
|
+
}
|
|
12541
|
+
value = value.replace(/\.+$/, "").toLowerCase();
|
|
12542
|
+
if (protocolMatch) {
|
|
12543
|
+
warnings.push(`Protocol stripped from input. Using "${value}".`);
|
|
12544
|
+
}
|
|
12545
|
+
if (/\s/.test(value) || !value.includes(".")) {
|
|
12546
|
+
throw new Error(
|
|
12547
|
+
`Invalid target: "${input}". Provide a domain like example.com or an IP like 192.168.1.1.`
|
|
12548
|
+
);
|
|
12549
|
+
}
|
|
12550
|
+
const assetType = detectAssetType(value);
|
|
12551
|
+
const parentDomain = deriveParentDomain(value);
|
|
12552
|
+
const isPubSuffix = isPublicSuffix(value);
|
|
12553
|
+
if (isPubSuffix) {
|
|
12554
|
+
warnings.push(
|
|
12555
|
+
`${value} is a public hosting suffix. You probably want your specific subdomain (e.g. myapp.${value}).`
|
|
12556
|
+
);
|
|
12557
|
+
}
|
|
12558
|
+
return {
|
|
12559
|
+
hostname: value,
|
|
12560
|
+
assetType,
|
|
12561
|
+
parentDomain,
|
|
12562
|
+
isPublicSuffix: isPubSuffix,
|
|
12563
|
+
warnings
|
|
12564
|
+
};
|
|
11868
12565
|
}
|
|
12566
|
+
|
|
12567
|
+
// src/commands/pentest.ts
|
|
11869
12568
|
function registerPentestCommand(program3) {
|
|
11870
12569
|
const pentest = program3.command("pentest").description("Run and manage pentests").option("-t, --target <domain>", "Target domain to pentest").option("--profile <id>", "Pentest profile ID (alternative to --target)").option("--mode <mode>", "Pentest mode", "full").option("-y, --yes", "Accept authorization terms without prompting").option("--no-watch", "Skip auto-watch after starting the pentest").option("--deployment <type>", "Deployment type: cloud or on-prem", "cloud").option("--include <hosts>", "Include only these subdomains (comma-separated)").option("--exclude <hosts>", "Exclude these subdomains (comma-separated)").option("--scope <action>", "Scope action: clear").addHelpText("after", `
|
|
11871
12570
|
Examples:
|
|
@@ -11912,31 +12611,33 @@ Examples:
|
|
|
11912
12611
|
targetDisplay = detail.domain_or_ip;
|
|
11913
12612
|
params = { scan_profile_id: options.profile };
|
|
11914
12613
|
} else {
|
|
11915
|
-
const
|
|
11916
|
-
|
|
11917
|
-
console.error(`Warning:
|
|
11918
|
-
}
|
|
11919
|
-
if (
|
|
11920
|
-
console.error(
|
|
11921
|
-
|
|
11922
|
-
|
|
12614
|
+
const parsed = parseTarget(options.target);
|
|
12615
|
+
for (const warning2 of parsed.warnings) {
|
|
12616
|
+
console.error(`Warning: ${warning2}`);
|
|
12617
|
+
}
|
|
12618
|
+
if (parsed.isPublicSuffix) {
|
|
12619
|
+
console.error(
|
|
12620
|
+
`
|
|
12621
|
+
${parsed.hostname} is a shared hosting domain. The server will likely reject this.`
|
|
12622
|
+
);
|
|
11923
12623
|
}
|
|
11924
12624
|
let asset;
|
|
11925
12625
|
try {
|
|
11926
|
-
asset = await client.assets.lookup(
|
|
12626
|
+
asset = await client.assets.lookup(parsed.hostname);
|
|
11927
12627
|
} catch (err) {
|
|
11928
12628
|
if (err instanceof ApiError && err.status === 404) {
|
|
11929
12629
|
asset = await client.assets.create({
|
|
11930
|
-
asset_type:
|
|
11931
|
-
asset_value:
|
|
12630
|
+
asset_type: parsed.assetType,
|
|
12631
|
+
asset_value: parsed.hostname,
|
|
12632
|
+
parent_domain: parsed.parentDomain,
|
|
11932
12633
|
verification_method: "dns"
|
|
11933
12634
|
});
|
|
11934
|
-
console.error(`Asset created for ${
|
|
12635
|
+
console.error(`Asset created for ${parsed.hostname}.`);
|
|
11935
12636
|
} else {
|
|
11936
12637
|
throw err;
|
|
11937
12638
|
}
|
|
11938
12639
|
}
|
|
11939
|
-
targetDisplay =
|
|
12640
|
+
targetDisplay = parsed.hostname;
|
|
11940
12641
|
const assetParams = {
|
|
11941
12642
|
asset_id: asset.id,
|
|
11942
12643
|
scan_mode: options.mode
|
|
@@ -11945,11 +12646,18 @@ Examples:
|
|
|
11945
12646
|
assetParams.deployment_type = options.deployment;
|
|
11946
12647
|
}
|
|
11947
12648
|
params = assetParams;
|
|
11948
|
-
if (scopeClear) {
|
|
12649
|
+
if (scopeClear || options.include || options.exclude) {
|
|
11949
12650
|
if (asset.asset_type !== "domain") {
|
|
11950
|
-
|
|
12651
|
+
const hint = parsed.parentDomain ? `
|
|
12652
|
+
Target the parent domain instead:
|
|
12653
|
+
kinosec pentest -t ${parsed.parentDomain} --${options.include ? "include" : "exclude"} ${parsed.hostname}` : "";
|
|
12654
|
+
console.error(
|
|
12655
|
+
`Error: Scope filtering is only available for domain assets. ${parsed.hostname} is a ${asset.asset_type}.${hint}`
|
|
12656
|
+
);
|
|
11951
12657
|
process.exit(2);
|
|
11952
12658
|
}
|
|
12659
|
+
}
|
|
12660
|
+
if (scopeClear) {
|
|
11953
12661
|
await client.assets.update(asset.id, {
|
|
11954
12662
|
scope_filter: null,
|
|
11955
12663
|
scope_hosts: null
|
|
@@ -11957,13 +12665,10 @@ Examples:
|
|
|
11957
12665
|
console.error("Scope settings cleared. Scans will now cover all subdomains by default.");
|
|
11958
12666
|
asset = await client.assets.get(asset.id);
|
|
11959
12667
|
} else if (options.include || options.exclude) {
|
|
11960
|
-
if (asset.asset_type !== "domain") {
|
|
11961
|
-
console.error("Error: Scope filtering is only available for domain assets.");
|
|
11962
|
-
process.exit(2);
|
|
11963
|
-
}
|
|
11964
12668
|
const mode = options.include ? "include" : "exclude";
|
|
11965
12669
|
const rawHosts = parseScopeHosts(options.include ?? options.exclude);
|
|
11966
12670
|
validateScopeHosts(rawHosts);
|
|
12671
|
+
validateScopeHostOwnership(rawHosts, asset.asset_value);
|
|
11967
12672
|
const scopeResult = await resolveScopeUpdate(asset, mode, rawHosts);
|
|
11968
12673
|
if (!scopeResult) {
|
|
11969
12674
|
process.exit(0);
|
|
@@ -12027,6 +12732,9 @@ ${divider}
|
|
|
12027
12732
|
showFindingsSummary: true
|
|
12028
12733
|
});
|
|
12029
12734
|
} catch (error2) {
|
|
12735
|
+
if (error2 instanceof Error && error2.message.startsWith("process.exit(")) {
|
|
12736
|
+
throw error2;
|
|
12737
|
+
}
|
|
12030
12738
|
handleError(error2);
|
|
12031
12739
|
}
|
|
12032
12740
|
});
|
|
@@ -12531,18 +13239,24 @@ Examples:
|
|
|
12531
13239
|
printJson(detail);
|
|
12532
13240
|
return;
|
|
12533
13241
|
}
|
|
12534
|
-
|
|
12535
|
-
["
|
|
12536
|
-
[
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
13242
|
+
const rows = [
|
|
13243
|
+
["ID", detail.id],
|
|
13244
|
+
["Value", detail.asset_value],
|
|
13245
|
+
["Type", detail.asset_type],
|
|
13246
|
+
["Status", detail.verification_status],
|
|
13247
|
+
["Parent", detail.parent_domain ?? "(none)"]
|
|
13248
|
+
];
|
|
13249
|
+
if (detail.asset_type === "domain") {
|
|
13250
|
+
rows.push(["Scope", detail.scope_filter ?? "all subdomains"]);
|
|
13251
|
+
if (detail.scope_hosts?.length) {
|
|
13252
|
+
rows.push(["Hosts", detail.scope_hosts.join(", ")]);
|
|
13253
|
+
}
|
|
13254
|
+
}
|
|
13255
|
+
rows.push(
|
|
13256
|
+
["Created", detail.created_at],
|
|
13257
|
+
["Updated", detail.updated_at]
|
|
12545
13258
|
);
|
|
13259
|
+
printTable(["Field", "Value"], rows);
|
|
12546
13260
|
} catch (error2) {
|
|
12547
13261
|
handleError(error2);
|
|
12548
13262
|
}
|
|
@@ -12555,11 +13269,18 @@ Examples:
|
|
|
12555
13269
|
const opts = program3.opts();
|
|
12556
13270
|
const { token, apiUrl } = resolveToken(opts);
|
|
12557
13271
|
const client = new KinoSecClient({ apiUrl, token });
|
|
13272
|
+
const detected = detectAssetType(options.value);
|
|
13273
|
+
if (detected !== options.type) {
|
|
13274
|
+
console.error(
|
|
13275
|
+
`Warning: ${options.value} looks like a ${detected}, not a ${options.type}. Continuing with your specified type.`
|
|
13276
|
+
);
|
|
13277
|
+
}
|
|
13278
|
+
const parentDomain = options.parent ?? (options.type === "subdomain" ? deriveParentDomain(options.value) : null);
|
|
12558
13279
|
const result = await client.assets.create({
|
|
12559
13280
|
asset_type: options.type,
|
|
12560
13281
|
asset_value: options.value,
|
|
12561
13282
|
verification_method: options.verifyMethod,
|
|
12562
|
-
parent_domain:
|
|
13283
|
+
parent_domain: parentDomain
|
|
12563
13284
|
});
|
|
12564
13285
|
if (opts.json || opts.output === "json") {
|
|
12565
13286
|
printJson(result);
|
|
@@ -12673,6 +13394,7 @@ Examples:
|
|
|
12673
13394
|
const mode = options.include ? "include" : "exclude";
|
|
12674
13395
|
const rawHosts = parseScopeHosts(options.include ?? options.exclude);
|
|
12675
13396
|
validateScopeHosts(rawHosts);
|
|
13397
|
+
validateScopeHostOwnership(rawHosts, asset2.asset_value);
|
|
12676
13398
|
const result = await resolveScopeUpdate(asset2, mode, rawHosts);
|
|
12677
13399
|
if (!result) return;
|
|
12678
13400
|
await client.assets.update(asset2.id, {
|
|
@@ -13068,7 +13790,7 @@ Examples:
|
|
|
13068
13790
|
|
|
13069
13791
|
// src/cli.ts
|
|
13070
13792
|
var program2 = new Command();
|
|
13071
|
-
program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.10.
|
|
13793
|
+
program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.10.2", "-v, --version").option("--token <pat>", "API token (overrides KINOSEC_TOKEN)").option("--output <format>", "Output format: text or json", "text").option("--json", "Shorthand for --output json").option("--no-color", "Disable colors");
|
|
13072
13794
|
registerAuthCommand(program2);
|
|
13073
13795
|
registerMeCommand(program2);
|
|
13074
13796
|
registerCreditsCommand(program2);
|
|
@@ -13077,7 +13799,7 @@ registerAssetCommand(program2);
|
|
|
13077
13799
|
registerFindingCommand(program2);
|
|
13078
13800
|
registerReportCommand(program2);
|
|
13079
13801
|
registerTokenCommand(program2);
|
|
13080
|
-
program2.parseAsync(process.argv).then(() => checkForUpdate("0.10.
|
|
13802
|
+
program2.parseAsync(process.argv).then(() => checkForUpdate("0.10.2")).catch(handleError);
|
|
13081
13803
|
/*! Bundled license information:
|
|
13082
13804
|
|
|
13083
13805
|
ky/distribution/index.js:
|