kinetex 1.0.0 → 1.1.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 +104 -16
- package/dist/browser/kinetex.esm.js +18 -18
- package/dist/browser/kinetex.js +509 -240
- package/dist/browser/kinetex.min.js +18 -18
- package/dist/cjs/client.js +180 -11
- package/dist/cjs/cookie-store.js +10 -0
- package/dist/cjs/core.js +25 -8
- package/dist/cjs/graphql.js +18 -4
- package/dist/cjs/logging.js +10 -2
- package/dist/cjs/mod.js +1 -1
- package/dist/cjs/pagination.js +6 -1
- package/dist/cjs/response.js +8 -6
- package/dist/cjs/sse.js +5 -2
- package/dist/cjs/utils.js +238 -57
- package/dist/cjs/ws.js +6 -1
- package/dist/esm/client.js +180 -11
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/cookie-store.js +10 -0
- package/dist/esm/cookie-store.js.map +1 -1
- package/dist/esm/core.js +25 -8
- package/dist/esm/core.js.map +1 -1
- package/dist/esm/graphql.js +18 -4
- package/dist/esm/graphql.js.map +1 -1
- package/dist/esm/logging.js +10 -2
- package/dist/esm/logging.js.map +1 -1
- package/dist/esm/mod.js +1 -1
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/pagination.js +6 -1
- package/dist/esm/pagination.js.map +1 -1
- package/dist/esm/response.js +8 -6
- package/dist/esm/response.js.map +1 -1
- package/dist/esm/sse.js +5 -2
- package/dist/esm/sse.js.map +1 -1
- package/dist/esm/utils.js +238 -57
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/ws.js +6 -1
- package/dist/esm/ws.js.map +1 -1
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/cookie-store.d.ts.map +1 -1
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/graphql.d.ts.map +1 -1
- package/dist/types/logging.d.ts.map +1 -1
- package/dist/types/mod.d.ts +1 -1
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/pagination.d.ts.map +1 -1
- package/dist/types/response.d.ts.map +1 -1
- package/dist/types/sse.d.ts.map +1 -1
- package/dist/types/utils.d.ts +18 -2
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/ws.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/browser/kinetex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* kinetex v1.
|
|
1
|
+
/* kinetex v1.1.0 | MIT | https://github.com/kinetexjs/kinetex */
|
|
2
2
|
"use strict";
|
|
3
3
|
var kinetex = (() => {
|
|
4
4
|
var __create = Object.create;
|
|
@@ -51,160 +51,6 @@ var kinetex = (() => {
|
|
|
51
51
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
52
52
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
53
53
|
|
|
54
|
-
// dist/esm/types.js
|
|
55
|
-
function toRequestId(id) {
|
|
56
|
-
return id;
|
|
57
|
-
}
|
|
58
|
-
function validateErrorCode(code) {
|
|
59
|
-
if (typeof code === "string") {
|
|
60
|
-
for (const valid of VALID_ERROR_CODES) {
|
|
61
|
-
if (valid === code)
|
|
62
|
-
return valid;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return void 0;
|
|
66
|
-
}
|
|
67
|
-
var VALID_ERROR_CODES, KinetexError, SizeLimitError, HTTPStatusError, AbortError, NetworkError, ValidationError, AuthError, ProxyError, RedirectError, TimeoutError;
|
|
68
|
-
var init_types = __esm({
|
|
69
|
-
"dist/esm/types.js"() {
|
|
70
|
-
"use strict";
|
|
71
|
-
VALID_ERROR_CODES = [
|
|
72
|
-
"ENETWORK",
|
|
73
|
-
"ETIMEOUT",
|
|
74
|
-
"EABORT",
|
|
75
|
-
"EHTTPSTATUS",
|
|
76
|
-
"ESIZELIMIT",
|
|
77
|
-
"EPARSE",
|
|
78
|
-
"EVALIDATION",
|
|
79
|
-
"EAUTH",
|
|
80
|
-
"EPROXY",
|
|
81
|
-
"EREDIRECT",
|
|
82
|
-
"EUNKNOWN"
|
|
83
|
-
];
|
|
84
|
-
KinetexError = class extends Error {
|
|
85
|
-
/**
|
|
86
|
-
* @param message - Human-readable error description.
|
|
87
|
-
* @param code - Machine-readable error code.
|
|
88
|
-
* @param options - Additional context (request, response, cause).
|
|
89
|
-
*/
|
|
90
|
-
constructor(message, code, options) {
|
|
91
|
-
super(message);
|
|
92
|
-
/** Machine-readable error code. */
|
|
93
|
-
__publicField(this, "code");
|
|
94
|
-
/** Original request, if available. */
|
|
95
|
-
__publicField(this, "request");
|
|
96
|
-
/** Response, if available (for HTTP-level errors). */
|
|
97
|
-
__publicField(this, "response");
|
|
98
|
-
/** Underlying cause. */
|
|
99
|
-
__publicField(this, "cause");
|
|
100
|
-
this.name = "KinetexError";
|
|
101
|
-
this.code = code;
|
|
102
|
-
if (options?.request !== void 0)
|
|
103
|
-
this.request = options.request;
|
|
104
|
-
if (options?.response !== void 0)
|
|
105
|
-
this.response = options.response;
|
|
106
|
-
if (options?.cause !== void 0)
|
|
107
|
-
this.cause = options.cause;
|
|
108
|
-
}
|
|
109
|
-
/** True if the error is a network/transport failure (not proxy-related). */
|
|
110
|
-
get isNetwork() {
|
|
111
|
-
return this.code === "ENETWORK";
|
|
112
|
-
}
|
|
113
|
-
/** True if the error is a proxy-related failure. */
|
|
114
|
-
get isProxy() {
|
|
115
|
-
return this.code === "EPROXY";
|
|
116
|
-
}
|
|
117
|
-
/** True if the error is a timeout. */
|
|
118
|
-
get isTimeout() {
|
|
119
|
-
return this.code === "ETIMEOUT";
|
|
120
|
-
}
|
|
121
|
-
/** True if the request was aborted by the caller. */
|
|
122
|
-
get isAbort() {
|
|
123
|
-
return this.code === "EABORT";
|
|
124
|
-
}
|
|
125
|
-
/** True if the server returned a 4xx or 5xx status. */
|
|
126
|
-
get isHTTPError() {
|
|
127
|
-
return this.code === "EHTTPSTATUS";
|
|
128
|
-
}
|
|
129
|
-
/** HTTP status code shorthand (null for non-HTTP errors). */
|
|
130
|
-
get status() {
|
|
131
|
-
return this.response?.status ?? null;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
SizeLimitError = class extends KinetexError {
|
|
135
|
-
constructor(bytesRead, limit, request) {
|
|
136
|
-
super(`Response size limit exceeded: ${bytesRead} bytes read, limit is ${limit} bytes`, "ESIZELIMIT", request !== void 0 ? { request } : {});
|
|
137
|
-
__publicField(this, "bytesRead");
|
|
138
|
-
__publicField(this, "limit");
|
|
139
|
-
this.bytesRead = bytesRead;
|
|
140
|
-
this.limit = limit;
|
|
141
|
-
this.name = "SizeLimitError";
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
HTTPStatusError = class extends KinetexError {
|
|
145
|
-
constructor(response, request) {
|
|
146
|
-
super(`HTTP ${response.status} ${response.statusText} \u2014 ${response.url}`, "EHTTPSTATUS", {
|
|
147
|
-
request,
|
|
148
|
-
response
|
|
149
|
-
});
|
|
150
|
-
this.name = "HTTPStatusError";
|
|
151
|
-
}
|
|
152
|
-
/** True if the status is a 4xx client error. */
|
|
153
|
-
get isClientError() {
|
|
154
|
-
return (this.status ?? 0) >= 400 && (this.status ?? 0) < 500;
|
|
155
|
-
}
|
|
156
|
-
/** True if the status is a 5xx server error. */
|
|
157
|
-
get isServerError() {
|
|
158
|
-
return (this.status ?? 0) >= 500;
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
AbortError = class extends KinetexError {
|
|
162
|
-
constructor(request) {
|
|
163
|
-
super("Request was aborted", "EABORT", request !== void 0 ? { request } : {});
|
|
164
|
-
this.name = "AbortError";
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
NetworkError = class extends KinetexError {
|
|
168
|
-
constructor(message, request) {
|
|
169
|
-
super(message, "ENETWORK", request !== void 0 ? { request } : {});
|
|
170
|
-
this.name = "NetworkError";
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
ValidationError = class extends KinetexError {
|
|
174
|
-
constructor(message, request) {
|
|
175
|
-
super(message, "EVALIDATION", request !== void 0 ? { request } : {});
|
|
176
|
-
this.name = "ValidationError";
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
AuthError = class extends KinetexError {
|
|
180
|
-
constructor(message, request) {
|
|
181
|
-
super(message, "EAUTH", request !== void 0 ? { request } : {});
|
|
182
|
-
this.name = "AuthError";
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
ProxyError = class extends KinetexError {
|
|
186
|
-
constructor(message, request) {
|
|
187
|
-
super(message, "EPROXY", request !== void 0 ? { request } : {});
|
|
188
|
-
this.name = "ProxyError";
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
RedirectError = class extends KinetexError {
|
|
192
|
-
constructor(message, request) {
|
|
193
|
-
super(message, "EREDIRECT", request !== void 0 ? { request } : {});
|
|
194
|
-
this.name = "RedirectError";
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
TimeoutError = class extends KinetexError {
|
|
198
|
-
constructor(timeoutMs, request) {
|
|
199
|
-
super(`Request timed out after ${timeoutMs}ms`, "ETIMEOUT", request !== void 0 ? { request } : {});
|
|
200
|
-
__publicField(this, "timeoutMs");
|
|
201
|
-
this.timeoutMs = timeoutMs;
|
|
202
|
-
this.name = "TimeoutError";
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
|
|
208
54
|
// dist/esm/utils.js
|
|
209
55
|
function getProcess() {
|
|
210
56
|
if (_process)
|
|
@@ -346,6 +192,25 @@ var kinetex = (() => {
|
|
|
346
192
|
const result = safeJSONParse(text);
|
|
347
193
|
return result.success ? result.value : text;
|
|
348
194
|
}
|
|
195
|
+
function sanitizeParsedJSON(value) {
|
|
196
|
+
if (value === null || typeof value !== "object")
|
|
197
|
+
return value;
|
|
198
|
+
if (Array.isArray(value)) {
|
|
199
|
+
for (let i = 0; i < value.length; i++) {
|
|
200
|
+
value[i] = sanitizeParsedJSON(value[i]);
|
|
201
|
+
}
|
|
202
|
+
return value;
|
|
203
|
+
}
|
|
204
|
+
const obj = value;
|
|
205
|
+
for (const key of Object.keys(obj)) {
|
|
206
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
207
|
+
delete obj[key];
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
sanitizeParsedJSON(obj[key]);
|
|
211
|
+
}
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
349
214
|
function parseUntrustedJSON(text) {
|
|
350
215
|
return safeJSONParse(text, {
|
|
351
216
|
maxDepth: 16,
|
|
@@ -401,6 +266,123 @@ var kinetex = (() => {
|
|
|
401
266
|
}
|
|
402
267
|
return true;
|
|
403
268
|
}
|
|
269
|
+
function isBlockedIPv4(n) {
|
|
270
|
+
return IPV4_BLOCKED_RANGES.some(([lo, hi]) => n >= lo && n <= hi);
|
|
271
|
+
}
|
|
272
|
+
function parseIPv4Component(p) {
|
|
273
|
+
if (p === "")
|
|
274
|
+
return null;
|
|
275
|
+
if (/^0[xX][0-9a-fA-F]+$/.test(p))
|
|
276
|
+
return parseInt(p, 16);
|
|
277
|
+
if (/^0[0-7]+$/.test(p))
|
|
278
|
+
return parseInt(p, 8);
|
|
279
|
+
if (/^\d+$/.test(p))
|
|
280
|
+
return parseInt(p, 10);
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
function parseIPv4Host(host) {
|
|
284
|
+
if (host.includes(":") || !/^[0-9a-fA-FxX.]+$/.test(host))
|
|
285
|
+
return null;
|
|
286
|
+
const parts = host.split(".");
|
|
287
|
+
if (parts.length > 4)
|
|
288
|
+
return null;
|
|
289
|
+
if (parts.length === 1) {
|
|
290
|
+
const v = parseIPv4Component(parts[0]);
|
|
291
|
+
if (v === null || v > 4294967295)
|
|
292
|
+
return null;
|
|
293
|
+
return v >>> 0;
|
|
294
|
+
}
|
|
295
|
+
const nums = [];
|
|
296
|
+
for (const p of parts) {
|
|
297
|
+
const v = parseIPv4Component(p);
|
|
298
|
+
const isLast = p === parts[parts.length - 1];
|
|
299
|
+
if (v === null || v > (isLast && nums.length === 3 ? 255 : 255))
|
|
300
|
+
return null;
|
|
301
|
+
nums.push(v);
|
|
302
|
+
}
|
|
303
|
+
while (nums.length < 4)
|
|
304
|
+
nums.push(0);
|
|
305
|
+
return (nums[0] << 24 | nums[1] << 16 | nums[2] << 8 | nums[3]) >>> 0;
|
|
306
|
+
}
|
|
307
|
+
function parseIPv6Host(host) {
|
|
308
|
+
if (!host.includes(":"))
|
|
309
|
+
return null;
|
|
310
|
+
const bare = host.split("%")[0];
|
|
311
|
+
const halves = bare.split("::");
|
|
312
|
+
if (halves.length > 2)
|
|
313
|
+
return null;
|
|
314
|
+
const expandGroups = (part) => {
|
|
315
|
+
if (part === "")
|
|
316
|
+
return [];
|
|
317
|
+
const groups = part.split(":");
|
|
318
|
+
const out = [];
|
|
319
|
+
for (let i = 0; i < groups.length; i++) {
|
|
320
|
+
const g2 = groups[i];
|
|
321
|
+
if (g2 === "")
|
|
322
|
+
return null;
|
|
323
|
+
if (g2.includes(".")) {
|
|
324
|
+
if (i !== groups.length - 1)
|
|
325
|
+
return null;
|
|
326
|
+
const n = parseIPv4Host(g2);
|
|
327
|
+
if (n === null)
|
|
328
|
+
return null;
|
|
329
|
+
out.push(n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255);
|
|
330
|
+
} else {
|
|
331
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(g2))
|
|
332
|
+
return null;
|
|
333
|
+
const v = parseInt(g2, 16);
|
|
334
|
+
out.push(v >>> 8 & 255, v & 255);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return out;
|
|
338
|
+
};
|
|
339
|
+
let bytes;
|
|
340
|
+
if (halves.length === 2) {
|
|
341
|
+
const left = expandGroups(halves[0]);
|
|
342
|
+
const right = expandGroups(halves[1]);
|
|
343
|
+
if (!left || !right)
|
|
344
|
+
return null;
|
|
345
|
+
const fill = 16 - left.length - right.length;
|
|
346
|
+
if (fill < 0)
|
|
347
|
+
return null;
|
|
348
|
+
bytes = [...left, ...new Array(fill).fill(0), ...right];
|
|
349
|
+
} else {
|
|
350
|
+
const all = expandGroups(bare);
|
|
351
|
+
if (!all || all.length !== 16)
|
|
352
|
+
return null;
|
|
353
|
+
bytes = all;
|
|
354
|
+
}
|
|
355
|
+
return bytes.length === 16 ? new Uint8Array(bytes) : null;
|
|
356
|
+
}
|
|
357
|
+
function isBlockedIPv6(b) {
|
|
358
|
+
const read32 = (i) => (b[i] << 24 | b[i + 1] << 16 | b[i + 2] << 8 | b[i + 3]) >>> 0;
|
|
359
|
+
if (b.every((x) => x === 0))
|
|
360
|
+
return true;
|
|
361
|
+
if (b.slice(0, 15).every((x) => x === 0) && b[15] === 1)
|
|
362
|
+
return true;
|
|
363
|
+
const first = b[0];
|
|
364
|
+
if ((first & 254) === 252)
|
|
365
|
+
return true;
|
|
366
|
+
if (first === 254 && (b[1] & 192) === 128)
|
|
367
|
+
return true;
|
|
368
|
+
if (first === 255)
|
|
369
|
+
return true;
|
|
370
|
+
if (b[0] === 32 && b[1] === 1 && b[2] === 13 && b[3] === 184)
|
|
371
|
+
return true;
|
|
372
|
+
if (b.slice(0, 10).every((x) => x === 0) && b[10] === 255 && b[11] === 255) {
|
|
373
|
+
return isBlockedIPv4(read32(12));
|
|
374
|
+
}
|
|
375
|
+
if (b.slice(0, 12).every((x) => x === 0)) {
|
|
376
|
+
return isBlockedIPv4(read32(12));
|
|
377
|
+
}
|
|
378
|
+
if (b[0] === 0 && b[1] === 100 && b[2] === 255 && b[3] === 155 && b.slice(4, 12).every((x) => x === 0)) {
|
|
379
|
+
return isBlockedIPv4(read32(12));
|
|
380
|
+
}
|
|
381
|
+
if (b[0] === 32 && b[1] === 2) {
|
|
382
|
+
return isBlockedIPv4(read32(2));
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
404
386
|
function isSafeURL(url, allowedSchemes = ["http", "https"]) {
|
|
405
387
|
try {
|
|
406
388
|
const parsed = typeof url === "string" ? new URL(url) : url;
|
|
@@ -412,14 +394,20 @@ var kinetex = (() => {
|
|
|
412
394
|
return false;
|
|
413
395
|
}
|
|
414
396
|
let host = parsed.hostname.toLowerCase();
|
|
415
|
-
|
|
397
|
+
const isV6Literal = host.startsWith("[") && host.endsWith("]");
|
|
398
|
+
if (isV6Literal)
|
|
416
399
|
host = host.slice(1, -1);
|
|
417
|
-
if (host === "0
|
|
418
|
-
host = "::1";
|
|
419
|
-
if (host === "localhost" || host === "0.0.0.0")
|
|
420
|
-
return false;
|
|
421
|
-
if (PRIVATE_IP_RANGES.some((r) => r.test(host)))
|
|
400
|
+
if (host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0")
|
|
422
401
|
return false;
|
|
402
|
+
if (isV6Literal || host.includes(":")) {
|
|
403
|
+
const v6 = parseIPv6Host(host);
|
|
404
|
+
if (v6 === null || isBlockedIPv6(v6))
|
|
405
|
+
return false;
|
|
406
|
+
} else {
|
|
407
|
+
const v4 = parseIPv4Host(host);
|
|
408
|
+
if (v4 !== null && isBlockedIPv4(v4))
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
423
411
|
if (parsed.hostname.includes("..") || parsed.pathname.includes("..")) {
|
|
424
412
|
return false;
|
|
425
413
|
}
|
|
@@ -463,6 +451,8 @@ var kinetex = (() => {
|
|
|
463
451
|
}
|
|
464
452
|
const cloned = {};
|
|
465
453
|
for (const key in value) {
|
|
454
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype")
|
|
455
|
+
continue;
|
|
466
456
|
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
467
457
|
cloned[key] = deepClone(value[key]);
|
|
468
458
|
}
|
|
@@ -619,17 +609,14 @@ var kinetex = (() => {
|
|
|
619
609
|
return false;
|
|
620
610
|
}
|
|
621
611
|
function randomBytes(byteCount) {
|
|
612
|
+
if (!Number.isInteger(byteCount) || byteCount < 0 || byteCount > 65536) {
|
|
613
|
+
throw new Error(`randomBytes: invalid byteCount ${byteCount}`);
|
|
614
|
+
}
|
|
622
615
|
const arr = new Uint8Array(byteCount);
|
|
623
616
|
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
624
617
|
crypto.getRandomValues(arr);
|
|
625
618
|
} else {
|
|
626
|
-
|
|
627
|
-
if (uuid.length >= byteCount * 2) {
|
|
628
|
-
return uuid.slice(0, byteCount * 2);
|
|
629
|
-
}
|
|
630
|
-
for (let i = 0; i < arr.length; i++) {
|
|
631
|
-
arr[i] = Math.floor(Math.random() * 256);
|
|
632
|
-
}
|
|
619
|
+
throw new Error("randomBytes: no CSPRNG available in this runtime \u2014 crypto.getRandomValues is required");
|
|
633
620
|
}
|
|
634
621
|
return Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
635
622
|
}
|
|
@@ -681,7 +668,7 @@ var kinetex = (() => {
|
|
|
681
668
|
});
|
|
682
669
|
return result;
|
|
683
670
|
}
|
|
684
|
-
var _process, _Buffer, DEFAULT_LIMITS, HEADER_NAME_PATTERN, FORBIDDEN_SCHEMES,
|
|
671
|
+
var _process, _Buffer, DEFAULT_LIMITS, HEADER_NAME_PATTERN, FORBIDDEN_SCHEMES, IPV4_BLOCKED_RANGES, cachedRuntime;
|
|
685
672
|
var init_utils = __esm({
|
|
686
673
|
"dist/esm/utils.js"() {
|
|
687
674
|
"use strict";
|
|
@@ -717,53 +704,194 @@ var kinetex = (() => {
|
|
|
717
704
|
"webcal",
|
|
718
705
|
"urn"
|
|
719
706
|
]);
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
//
|
|
723
|
-
|
|
724
|
-
// RFC 1918
|
|
725
|
-
|
|
726
|
-
// RFC
|
|
727
|
-
|
|
728
|
-
//
|
|
729
|
-
|
|
730
|
-
// link-local (AWS IMDS
|
|
731
|
-
|
|
732
|
-
//
|
|
733
|
-
|
|
734
|
-
//
|
|
735
|
-
|
|
736
|
-
//
|
|
737
|
-
|
|
738
|
-
//
|
|
739
|
-
|
|
740
|
-
//
|
|
741
|
-
|
|
742
|
-
//
|
|
743
|
-
|
|
744
|
-
//
|
|
745
|
-
|
|
746
|
-
//
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
// IPv4-mapped loopback
|
|
750
|
-
/^::ffff:10\./i,
|
|
751
|
-
// IPv4-mapped RFC 1918
|
|
752
|
-
/^::ffff:192\.168\./i,
|
|
753
|
-
// IPv4-mapped RFC 1918
|
|
754
|
-
/^::ffff:172\.(1[6-9]|2\d|3[01])\./i,
|
|
755
|
-
// IPv4-mapped RFC 1918
|
|
756
|
-
/^::ffff:169\.254\./i,
|
|
757
|
-
// IPv4-mapped link-local
|
|
758
|
-
/^0:0:0:0:0:ffff:7f/i,
|
|
759
|
-
// compressed form of ::ffff:127.x
|
|
760
|
-
/^::$/i
|
|
761
|
-
// IPv4-compatible :: (any ::/96)
|
|
707
|
+
IPV4_BLOCKED_RANGES = [
|
|
708
|
+
[0, 16777215],
|
|
709
|
+
// 0.0.0.0/8 — this-network
|
|
710
|
+
[167772160, 184549375],
|
|
711
|
+
// 10.0.0.0/8 — RFC 1918 private
|
|
712
|
+
[1681915904, 1686110207],
|
|
713
|
+
// 100.64.0.0/10 — CGNAT (RFC 6598)
|
|
714
|
+
[2130706432, 2147483647],
|
|
715
|
+
// 127.0.0.0/8 — loopback
|
|
716
|
+
[2851995648, 2852061183],
|
|
717
|
+
// 169.254.0.0/16 — link-local (AWS IMDS etc.)
|
|
718
|
+
[2886729728, 2887778303],
|
|
719
|
+
// 172.16.0.0/12 — RFC 1918 private
|
|
720
|
+
[3221225472, 3221225727],
|
|
721
|
+
// 192.0.0.0/24 — IETF protocol assignments
|
|
722
|
+
[3221225984, 3221226239],
|
|
723
|
+
// 192.0.2.0/24 — TEST-NET-1
|
|
724
|
+
[3232235520, 3232301055],
|
|
725
|
+
// 192.168.0.0/16 — RFC 1918 private
|
|
726
|
+
[3323068416, 3323199487],
|
|
727
|
+
// 198.18.0.0/15 — benchmarking
|
|
728
|
+
[3325256704, 3325256959],
|
|
729
|
+
// 198.51.100.0/24 — TEST-NET-2
|
|
730
|
+
[3405803776, 3405804031],
|
|
731
|
+
// 203.0.113.0/24 — TEST-NET-3
|
|
732
|
+
[3758096384, 4026531839],
|
|
733
|
+
// 224.0.0.0/4 — multicast
|
|
734
|
+
[4026531840, 4294967295]
|
|
735
|
+
// 240.0.0.0/4 — reserved (incl. 255.255.255.255)
|
|
762
736
|
];
|
|
763
737
|
cachedRuntime = null;
|
|
764
738
|
}
|
|
765
739
|
});
|
|
766
740
|
|
|
741
|
+
// dist/esm/types.js
|
|
742
|
+
function toRequestId(id) {
|
|
743
|
+
return id;
|
|
744
|
+
}
|
|
745
|
+
function validateErrorCode(code) {
|
|
746
|
+
if (typeof code === "string") {
|
|
747
|
+
for (const valid of VALID_ERROR_CODES) {
|
|
748
|
+
if (valid === code)
|
|
749
|
+
return valid;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return void 0;
|
|
753
|
+
}
|
|
754
|
+
var VALID_ERROR_CODES, KinetexError, SizeLimitError, HTTPStatusError, AbortError, NetworkError, ValidationError, AuthError, ProxyError, RedirectError, TimeoutError;
|
|
755
|
+
var init_types = __esm({
|
|
756
|
+
"dist/esm/types.js"() {
|
|
757
|
+
"use strict";
|
|
758
|
+
VALID_ERROR_CODES = [
|
|
759
|
+
"ENETWORK",
|
|
760
|
+
"ETIMEOUT",
|
|
761
|
+
"EABORT",
|
|
762
|
+
"EHTTPSTATUS",
|
|
763
|
+
"ESIZELIMIT",
|
|
764
|
+
"EPARSE",
|
|
765
|
+
"EVALIDATION",
|
|
766
|
+
"EAUTH",
|
|
767
|
+
"EPROXY",
|
|
768
|
+
"EREDIRECT",
|
|
769
|
+
"EUNKNOWN"
|
|
770
|
+
];
|
|
771
|
+
KinetexError = class extends Error {
|
|
772
|
+
/**
|
|
773
|
+
* @param message - Human-readable error description.
|
|
774
|
+
* @param code - Machine-readable error code.
|
|
775
|
+
* @param options - Additional context (request, response, cause).
|
|
776
|
+
*/
|
|
777
|
+
constructor(message, code, options) {
|
|
778
|
+
super(message);
|
|
779
|
+
/** Machine-readable error code. */
|
|
780
|
+
__publicField(this, "code");
|
|
781
|
+
/** Original request, if available. */
|
|
782
|
+
__publicField(this, "request");
|
|
783
|
+
/** Response, if available (for HTTP-level errors). */
|
|
784
|
+
__publicField(this, "response");
|
|
785
|
+
/** Underlying cause. */
|
|
786
|
+
__publicField(this, "cause");
|
|
787
|
+
this.name = "KinetexError";
|
|
788
|
+
this.code = code;
|
|
789
|
+
if (options?.request !== void 0)
|
|
790
|
+
this.request = options.request;
|
|
791
|
+
if (options?.response !== void 0)
|
|
792
|
+
this.response = options.response;
|
|
793
|
+
if (options?.cause !== void 0)
|
|
794
|
+
this.cause = options.cause;
|
|
795
|
+
}
|
|
796
|
+
/** True if the error is a network/transport failure (not proxy-related). */
|
|
797
|
+
get isNetwork() {
|
|
798
|
+
return this.code === "ENETWORK";
|
|
799
|
+
}
|
|
800
|
+
/** True if the error is a proxy-related failure. */
|
|
801
|
+
get isProxy() {
|
|
802
|
+
return this.code === "EPROXY";
|
|
803
|
+
}
|
|
804
|
+
/** True if the error is a timeout. */
|
|
805
|
+
get isTimeout() {
|
|
806
|
+
return this.code === "ETIMEOUT";
|
|
807
|
+
}
|
|
808
|
+
/** True if the request was aborted by the caller. */
|
|
809
|
+
get isAbort() {
|
|
810
|
+
return this.code === "EABORT";
|
|
811
|
+
}
|
|
812
|
+
/** True if the server returned a 4xx or 5xx status. */
|
|
813
|
+
get isHTTPError() {
|
|
814
|
+
return this.code === "EHTTPSTATUS";
|
|
815
|
+
}
|
|
816
|
+
/** HTTP status code shorthand (null for non-HTTP errors). */
|
|
817
|
+
get status() {
|
|
818
|
+
return this.response?.status ?? null;
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
SizeLimitError = class extends KinetexError {
|
|
822
|
+
constructor(bytesRead, limit, request) {
|
|
823
|
+
super(`Response size limit exceeded: ${bytesRead} bytes read, limit is ${limit} bytes`, "ESIZELIMIT", request !== void 0 ? { request } : {});
|
|
824
|
+
__publicField(this, "bytesRead");
|
|
825
|
+
__publicField(this, "limit");
|
|
826
|
+
this.bytesRead = bytesRead;
|
|
827
|
+
this.limit = limit;
|
|
828
|
+
this.name = "SizeLimitError";
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
HTTPStatusError = class extends KinetexError {
|
|
832
|
+
constructor(response, request) {
|
|
833
|
+
super(`HTTP ${response.status} ${response.statusText} \u2014 ${response.url}`, "EHTTPSTATUS", {
|
|
834
|
+
request,
|
|
835
|
+
response
|
|
836
|
+
});
|
|
837
|
+
this.name = "HTTPStatusError";
|
|
838
|
+
}
|
|
839
|
+
/** True if the status is a 4xx client error. */
|
|
840
|
+
get isClientError() {
|
|
841
|
+
return (this.status ?? 0) >= 400 && (this.status ?? 0) < 500;
|
|
842
|
+
}
|
|
843
|
+
/** True if the status is a 5xx server error. */
|
|
844
|
+
get isServerError() {
|
|
845
|
+
return (this.status ?? 0) >= 500;
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
AbortError = class extends KinetexError {
|
|
849
|
+
constructor(request) {
|
|
850
|
+
super("Request was aborted", "EABORT", request !== void 0 ? { request } : {});
|
|
851
|
+
this.name = "AbortError";
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
NetworkError = class extends KinetexError {
|
|
855
|
+
constructor(message, request) {
|
|
856
|
+
super(message, "ENETWORK", request !== void 0 ? { request } : {});
|
|
857
|
+
this.name = "NetworkError";
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
ValidationError = class extends KinetexError {
|
|
861
|
+
constructor(message, request) {
|
|
862
|
+
super(message, "EVALIDATION", request !== void 0 ? { request } : {});
|
|
863
|
+
this.name = "ValidationError";
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
AuthError = class extends KinetexError {
|
|
867
|
+
constructor(message, request) {
|
|
868
|
+
super(message, "EAUTH", request !== void 0 ? { request } : {});
|
|
869
|
+
this.name = "AuthError";
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
ProxyError = class extends KinetexError {
|
|
873
|
+
constructor(message, request) {
|
|
874
|
+
super(message, "EPROXY", request !== void 0 ? { request } : {});
|
|
875
|
+
this.name = "ProxyError";
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
RedirectError = class extends KinetexError {
|
|
879
|
+
constructor(message, request) {
|
|
880
|
+
super(message, "EREDIRECT", request !== void 0 ? { request } : {});
|
|
881
|
+
this.name = "RedirectError";
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
TimeoutError = class extends KinetexError {
|
|
885
|
+
constructor(timeoutMs, request) {
|
|
886
|
+
super(`Request timed out after ${timeoutMs}ms`, "ETIMEOUT", request !== void 0 ? { request } : {});
|
|
887
|
+
__publicField(this, "timeoutMs");
|
|
888
|
+
this.timeoutMs = timeoutMs;
|
|
889
|
+
this.name = "TimeoutError";
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
|
|
767
895
|
// dist/esm/cache.js
|
|
768
896
|
var cache_exports = {};
|
|
769
897
|
__export(cache_exports, {
|
|
@@ -3706,7 +3834,7 @@ var kinetex = (() => {
|
|
|
3706
3834
|
const charset = options.charset ?? parseContentType2(ct ?? "")?.charset ?? null;
|
|
3707
3835
|
const text = decodeBody(bytes, charset, url);
|
|
3708
3836
|
try {
|
|
3709
|
-
return JSON.parse(text);
|
|
3837
|
+
return sanitizeParsedJSON(JSON.parse(text));
|
|
3710
3838
|
} catch (err) {
|
|
3711
3839
|
throw new ResponseDecodeError(`JSON parse failed: ${err}`, "json", url);
|
|
3712
3840
|
}
|
|
@@ -3761,7 +3889,7 @@ var kinetex = (() => {
|
|
|
3761
3889
|
const trimmed = buffer.trim();
|
|
3762
3890
|
if (trimmed) {
|
|
3763
3891
|
try {
|
|
3764
|
-
yield JSON.parse(trimmed);
|
|
3892
|
+
yield sanitizeParsedJSON(JSON.parse(trimmed));
|
|
3765
3893
|
} catch (err) {
|
|
3766
3894
|
options.onParseError?.(err, trimmed);
|
|
3767
3895
|
}
|
|
@@ -3776,7 +3904,7 @@ var kinetex = (() => {
|
|
|
3776
3904
|
if (!trimmed || trimmed.startsWith("#"))
|
|
3777
3905
|
continue;
|
|
3778
3906
|
try {
|
|
3779
|
-
yield JSON.parse(trimmed);
|
|
3907
|
+
yield sanitizeParsedJSON(JSON.parse(trimmed));
|
|
3780
3908
|
} catch (err) {
|
|
3781
3909
|
options.onParseError?.(err, trimmed);
|
|
3782
3910
|
}
|
|
@@ -3809,7 +3937,7 @@ var kinetex = (() => {
|
|
|
3809
3937
|
const remaining = flushBuffer();
|
|
3810
3938
|
if (remaining) {
|
|
3811
3939
|
try {
|
|
3812
|
-
const obj = JSON.parse(remaining);
|
|
3940
|
+
const obj = sanitizeParsedJSON(JSON.parse(remaining));
|
|
3813
3941
|
options.onObject?.(obj);
|
|
3814
3942
|
yield obj;
|
|
3815
3943
|
} catch (err) {
|
|
@@ -3830,7 +3958,7 @@ var kinetex = (() => {
|
|
|
3830
3958
|
if (depth === 0 && startIdx !== -1) {
|
|
3831
3959
|
const objStr = buffer.slice(startIdx, i + 1);
|
|
3832
3960
|
try {
|
|
3833
|
-
const obj = JSON.parse(objStr);
|
|
3961
|
+
const obj = sanitizeParsedJSON(JSON.parse(objStr));
|
|
3834
3962
|
options.onObject?.(obj);
|
|
3835
3963
|
yield obj;
|
|
3836
3964
|
} catch (err) {
|
|
@@ -4374,7 +4502,7 @@ var kinetex = (() => {
|
|
|
4374
4502
|
}
|
|
4375
4503
|
}
|
|
4376
4504
|
function createTransport(fetchFn, preferHTTP2 = true, sessionOptions, transportOptions) {
|
|
4377
|
-
if (IS_NODE && preferHTTP2) {
|
|
4505
|
+
if (IS_NODE && preferHTTP2 && !fetchFn) {
|
|
4378
4506
|
return new NodeHTTP2Transport({
|
|
4379
4507
|
...sessionOptions?.sessionTTLMs !== void 0 ? { sessionTTLMs: sessionOptions.sessionTTLMs } : {},
|
|
4380
4508
|
...sessionOptions?.pingIntervalMs !== void 0 ? { pingIntervalMs: sessionOptions.pingIntervalMs } : {},
|
|
@@ -4399,8 +4527,11 @@ var kinetex = (() => {
|
|
|
4399
4527
|
}, timeoutMs);
|
|
4400
4528
|
const signal = mergeSignals(request.signal, controller.signal) ?? null;
|
|
4401
4529
|
const req = { ...request, signal };
|
|
4530
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
4531
|
+
controller.signal.addEventListener("abort", () => reject(new TimeoutError(timeoutMs, request)), { once: true });
|
|
4532
|
+
});
|
|
4402
4533
|
try {
|
|
4403
|
-
const result = await transport.send(req);
|
|
4534
|
+
const result = await Promise.race([transport.send(req), timeoutPromise]);
|
|
4404
4535
|
clearTimeout(timer);
|
|
4405
4536
|
if (controller.signal.aborted) {
|
|
4406
4537
|
throw new TimeoutError(timeoutMs, request);
|
|
@@ -4408,7 +4539,7 @@ var kinetex = (() => {
|
|
|
4408
4539
|
return result;
|
|
4409
4540
|
} catch (err) {
|
|
4410
4541
|
clearTimeout(timer);
|
|
4411
|
-
if (controller.signal.aborted) {
|
|
4542
|
+
if (controller.signal.aborted && !(err instanceof TimeoutError)) {
|
|
4412
4543
|
throw new TimeoutError(timeoutMs, request);
|
|
4413
4544
|
}
|
|
4414
4545
|
throw err;
|
|
@@ -4969,12 +5100,15 @@ var kinetex = (() => {
|
|
|
4969
5100
|
}
|
|
4970
5101
|
}
|
|
4971
5102
|
if (hasForbidden) {
|
|
5103
|
+
if (this._strict) {
|
|
5104
|
+
throw new KinetexError(`Strict mode: header "${hName}" contains forbidden control characters`, "EVALIDATION", { request: currentReq });
|
|
5105
|
+
}
|
|
4972
5106
|
if (this._onDroppedHeader) {
|
|
4973
5107
|
this._onDroppedHeader(hName, hStr);
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
throw new KinetexError(`Strict mode: header "${hName}" contains forbidden control characters`, "EVALIDATION", { request: currentReq });
|
|
5108
|
+
} else if (typeof console !== "undefined") {
|
|
5109
|
+
console.warn(`[kinetex] Invalid header dropped (HTTP/2): "${hName}" \u2014 value contains illegal control characters. Pass strictHeaders: true to throw instead.`);
|
|
4977
5110
|
}
|
|
5111
|
+
delete h2ReqHeaders[hName];
|
|
4978
5112
|
}
|
|
4979
5113
|
}
|
|
4980
5114
|
}
|
|
@@ -7325,6 +7459,10 @@ var kinetex = (() => {
|
|
|
7325
7459
|
continue;
|
|
7326
7460
|
if (!sameSiteAllows(cookie.sameSite, context))
|
|
7327
7461
|
continue;
|
|
7462
|
+
if (cookie.name.startsWith("__Secure-") && !(cookie.secure && isSecure))
|
|
7463
|
+
continue;
|
|
7464
|
+
if (cookie.name.startsWith("__Host-") && !(cookie.secure && isSecure && cookie.path === "/" && cookie.hostOnly))
|
|
7465
|
+
continue;
|
|
7328
7466
|
result.push(cookie);
|
|
7329
7467
|
}
|
|
7330
7468
|
}
|
|
@@ -7797,9 +7935,11 @@ var kinetex = (() => {
|
|
|
7797
7935
|
const [head, ...rest] = path;
|
|
7798
7936
|
if (head === void 0)
|
|
7799
7937
|
return;
|
|
7938
|
+
if (head === "__proto__" || head === "constructor" || head === "prototype")
|
|
7939
|
+
return;
|
|
7800
7940
|
const o = obj;
|
|
7801
7941
|
if (rest.length === 0) {
|
|
7802
|
-
if (head
|
|
7942
|
+
if (Object.prototype.hasOwnProperty.call(o, head))
|
|
7803
7943
|
o[head] = "***";
|
|
7804
7944
|
return;
|
|
7805
7945
|
}
|
|
@@ -7882,6 +8022,7 @@ var kinetex = (() => {
|
|
|
7882
8022
|
var init_logging = __esm({
|
|
7883
8023
|
"dist/esm/logging.js"() {
|
|
7884
8024
|
"use strict";
|
|
8025
|
+
init_utils();
|
|
7885
8026
|
getNodeEnv = () => {
|
|
7886
8027
|
try {
|
|
7887
8028
|
return globalThis.process?.env?.["NODE_ENV"];
|
|
@@ -8241,7 +8382,7 @@ var kinetex = (() => {
|
|
|
8241
8382
|
const size = str.length;
|
|
8242
8383
|
if (ct.includes("application/json") && this.bodyFields.length > 0) {
|
|
8243
8384
|
try {
|
|
8244
|
-
const parsed = JSON.parse(str);
|
|
8385
|
+
const parsed = sanitizeParsedJSON(JSON.parse(str));
|
|
8245
8386
|
for (const path of this.bodyFields)
|
|
8246
8387
|
redactObjectPath(parsed, path.split("."));
|
|
8247
8388
|
str = JSON.stringify(parsed);
|
|
@@ -8512,7 +8653,7 @@ var kinetex = (() => {
|
|
|
8512
8653
|
if (!evt.data && evt.data !== "")
|
|
8513
8654
|
continue;
|
|
8514
8655
|
try {
|
|
8515
|
-
const data = JSON.parse(evt.data, options.reviver);
|
|
8656
|
+
const data = sanitizeParsedJSON(JSON.parse(evt.data, options.reviver));
|
|
8516
8657
|
yield { event: evt.event, data, id: evt.id };
|
|
8517
8658
|
} catch (err) {
|
|
8518
8659
|
options.onError?.(err, evt);
|
|
@@ -8552,6 +8693,7 @@ var kinetex = (() => {
|
|
|
8552
8693
|
var init_sse = __esm({
|
|
8553
8694
|
"dist/esm/sse.js"() {
|
|
8554
8695
|
"use strict";
|
|
8696
|
+
init_utils();
|
|
8555
8697
|
SSEParser = class {
|
|
8556
8698
|
constructor() {
|
|
8557
8699
|
__publicField(this, "lines", []);
|
|
@@ -8991,7 +9133,7 @@ var kinetex = (() => {
|
|
|
8991
9133
|
onJSON(eventType, handler) {
|
|
8992
9134
|
return this.on(eventType, async (data, evt) => {
|
|
8993
9135
|
try {
|
|
8994
|
-
const parsed = JSON.parse(data);
|
|
9136
|
+
const parsed = sanitizeParsedJSON(JSON.parse(data));
|
|
8995
9137
|
await handler(parsed, evt);
|
|
8996
9138
|
} catch {
|
|
8997
9139
|
}
|
|
@@ -9315,11 +9457,18 @@ var kinetex = (() => {
|
|
|
9315
9457
|
let current = obj;
|
|
9316
9458
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
9317
9459
|
const key = parts[i];
|
|
9460
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
9461
|
+
throw new ValidationError(`Invalid upload path: "${path}" \u2014 reserved key "${key}"`);
|
|
9462
|
+
}
|
|
9318
9463
|
if (!current[key] || typeof current[key] !== "object")
|
|
9319
9464
|
current[key] = {};
|
|
9320
9465
|
current = current[key];
|
|
9321
9466
|
}
|
|
9322
|
-
|
|
9467
|
+
const leaf = parts[parts.length - 1];
|
|
9468
|
+
if (leaf === "__proto__" || leaf === "constructor" || leaf === "prototype") {
|
|
9469
|
+
throw new ValidationError(`Invalid upload path: "${path}" \u2014 reserved key "${leaf}"`);
|
|
9470
|
+
}
|
|
9471
|
+
current[leaf] = value;
|
|
9323
9472
|
}
|
|
9324
9473
|
async function parseGraphQLResponse(response, req) {
|
|
9325
9474
|
const ct = response.headers.get("content-type") ?? "";
|
|
@@ -9330,7 +9479,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
9330
9479
|
}
|
|
9331
9480
|
let json;
|
|
9332
9481
|
try {
|
|
9333
|
-
json = await response.json();
|
|
9482
|
+
json = sanitizeParsedJSON(await response.json());
|
|
9334
9483
|
} catch (err) {
|
|
9335
9484
|
throw new GraphQLClientError("Failed to parse GraphQL response as JSON", "EPARSE", void 0, req, void 0, err);
|
|
9336
9485
|
}
|
|
@@ -9477,6 +9626,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
9477
9626
|
"dist/esm/graphql.js"() {
|
|
9478
9627
|
"use strict";
|
|
9479
9628
|
init_types();
|
|
9629
|
+
init_utils();
|
|
9480
9630
|
GraphQLClientError = class extends Error {
|
|
9481
9631
|
/**
|
|
9482
9632
|
* @param message - Human-readable error description
|
|
@@ -9798,7 +9948,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
9798
9948
|
} catch (err) {
|
|
9799
9949
|
throw new GraphQLClientError(err instanceof Error ? err.message : "Batch network error", "ENETWORK", void 0, requests[0], void 0, err);
|
|
9800
9950
|
}
|
|
9801
|
-
const rawResults = await response.json();
|
|
9951
|
+
const rawResults = sanitizeParsedJSON(await response.json());
|
|
9802
9952
|
if (!Array.isArray(rawResults)) {
|
|
9803
9953
|
throw new GraphQLClientError("Batch response must be an array of GraphQL responses", "EINVALIDRESPONSE", void 0, requests[0], rawResults);
|
|
9804
9954
|
}
|
|
@@ -9886,7 +10036,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
9886
10036
|
continue;
|
|
9887
10037
|
let gqlRes;
|
|
9888
10038
|
try {
|
|
9889
|
-
gqlRes = JSON.parse(event.data);
|
|
10039
|
+
gqlRes = sanitizeParsedJSON(JSON.parse(event.data));
|
|
9890
10040
|
} catch {
|
|
9891
10041
|
continue;
|
|
9892
10042
|
}
|
|
@@ -10413,7 +10563,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
10413
10563
|
}
|
|
10414
10564
|
function deserializePaginationState(serialized) {
|
|
10415
10565
|
try {
|
|
10416
|
-
return JSON.parse(atob(serialized));
|
|
10566
|
+
return sanitizeParsedJSON(JSON.parse(atob(serialized)));
|
|
10417
10567
|
} catch {
|
|
10418
10568
|
throw new Error("Invalid pagination state string");
|
|
10419
10569
|
}
|
|
@@ -10460,6 +10610,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
10460
10610
|
var init_pagination = __esm({
|
|
10461
10611
|
"dist/esm/pagination.js"() {
|
|
10462
10612
|
"use strict";
|
|
10613
|
+
init_utils();
|
|
10463
10614
|
}
|
|
10464
10615
|
});
|
|
10465
10616
|
|
|
@@ -10768,6 +10919,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
10768
10919
|
retryLink: () => retryLink,
|
|
10769
10920
|
safeJSONParse: () => safeJSONParse,
|
|
10770
10921
|
safeParseURL: () => safeParseURL,
|
|
10922
|
+
sanitizeParsedJSON: () => sanitizeParsedJSON,
|
|
10771
10923
|
sanitizeURL: () => sanitizeURL,
|
|
10772
10924
|
securityHeaders: () => securityHeaders,
|
|
10773
10925
|
sendWithTimeout: () => sendWithTimeout,
|
|
@@ -11782,6 +11934,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
11782
11934
|
}
|
|
11783
11935
|
|
|
11784
11936
|
// dist/esm/ws.js
|
|
11937
|
+
init_utils();
|
|
11785
11938
|
var WSError = class extends Error {
|
|
11786
11939
|
/**
|
|
11787
11940
|
* @param message - Human-readable error description
|
|
@@ -12452,7 +12605,7 @@ ${text}`, "ENETWORK", void 0, req, void 0, new Error(`HTTP ${response.status}`))
|
|
|
12452
12605
|
data = evt.data;
|
|
12453
12606
|
bytes = new TextEncoder().encode(data).byteLength;
|
|
12454
12607
|
try {
|
|
12455
|
-
json = JSON.parse(data);
|
|
12608
|
+
json = sanitizeParsedJSON(JSON.parse(data));
|
|
12456
12609
|
} catch {
|
|
12457
12610
|
}
|
|
12458
12611
|
} else if (evt.data instanceof ArrayBuffer) {
|
|
@@ -14868,6 +15021,34 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
14868
15021
|
function randomHex(len) {
|
|
14869
15022
|
return randomBytes(len / 2);
|
|
14870
15023
|
}
|
|
15024
|
+
var HAR_REDACT_HEADERS = /* @__PURE__ */ new Set([
|
|
15025
|
+
"authorization",
|
|
15026
|
+
"proxy-authorization",
|
|
15027
|
+
"cookie",
|
|
15028
|
+
"set-cookie",
|
|
15029
|
+
"x-api-key",
|
|
15030
|
+
"x-auth-token",
|
|
15031
|
+
"x-access-token",
|
|
15032
|
+
"x-refresh-token",
|
|
15033
|
+
"x-csrf-token",
|
|
15034
|
+
"x-session-id",
|
|
15035
|
+
"x-session-token",
|
|
15036
|
+
"x-secret",
|
|
15037
|
+
"x-secret-key",
|
|
15038
|
+
"x-private-key",
|
|
15039
|
+
"api-key",
|
|
15040
|
+
"apikey",
|
|
15041
|
+
"bearer",
|
|
15042
|
+
"token",
|
|
15043
|
+
"authentication",
|
|
15044
|
+
"credentials",
|
|
15045
|
+
"password",
|
|
15046
|
+
"passwd",
|
|
15047
|
+
"secret"
|
|
15048
|
+
]);
|
|
15049
|
+
function redactHARHeader(name, value) {
|
|
15050
|
+
return HAR_REDACT_HEADERS.has(name.toLowerCase()) ? { name, value: "***REDACTED***" } : { name, value };
|
|
15051
|
+
}
|
|
14871
15052
|
var HARRecorder = class {
|
|
14872
15053
|
/**
|
|
14873
15054
|
* @param maxEntries - Maximum number of entries before eviction (default 10000).
|
|
@@ -14919,7 +15100,7 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
14919
15100
|
method: req.method,
|
|
14920
15101
|
url: req.url,
|
|
14921
15102
|
httpVersion: res.httpVersion,
|
|
14922
|
-
headers: Object.entries(req.headers).map(([name, value]) => (
|
|
15103
|
+
headers: Object.entries(req.headers).map(([name, value]) => redactHARHeader(name, value)),
|
|
14923
15104
|
queryString: (() => {
|
|
14924
15105
|
try {
|
|
14925
15106
|
return Array.from(new URL(req.url).searchParams.entries()).map(([name, value]) => ({
|
|
@@ -14946,7 +15127,7 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
14946
15127
|
status: res.status,
|
|
14947
15128
|
statusText: res.statusText,
|
|
14948
15129
|
httpVersion: res.httpVersion,
|
|
14949
|
-
headers: Object.entries(res.headers).map(([name, value]) => (
|
|
15130
|
+
headers: Object.entries(res.headers).map(([name, value]) => redactHARHeader(name, value)),
|
|
14950
15131
|
content: {
|
|
14951
15132
|
size: res.rawBody?.byteLength ?? 0,
|
|
14952
15133
|
mimeType: res.headers["content-type"] ?? "application/octet-stream",
|
|
@@ -14994,7 +15175,11 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
14994
15175
|
switch (auth.type) {
|
|
14995
15176
|
case "bearer": {
|
|
14996
15177
|
const token = typeof auth.token === "function" ? await auth.token() : auth.token;
|
|
14997
|
-
|
|
15178
|
+
const headerValue = `Bearer ${token}`;
|
|
15179
|
+
if (!isValidHeaderValue(headerValue)) {
|
|
15180
|
+
throw new KinetexError("Invalid bearer token \u2014 contains forbidden characters (CRLF/CTL)", "EVALIDATION");
|
|
15181
|
+
}
|
|
15182
|
+
headers["authorization"] = headerValue;
|
|
14998
15183
|
break;
|
|
14999
15184
|
}
|
|
15000
15185
|
case "basic": {
|
|
@@ -15015,7 +15200,13 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15015
15200
|
}
|
|
15016
15201
|
case "apikey": {
|
|
15017
15202
|
const key = typeof auth.key === "function" ? await auth.key() : auth.key;
|
|
15018
|
-
|
|
15203
|
+
if (!isValidHeaderName(auth.header)) {
|
|
15204
|
+
throw new KinetexError(`Invalid apikey auth header name: "${auth.header}"`, "EVALIDATION");
|
|
15205
|
+
}
|
|
15206
|
+
if (!isValidHeaderValue(String(key))) {
|
|
15207
|
+
throw new KinetexError(`Invalid apikey value for "${auth.header}" \u2014 contains forbidden characters`, "EVALIDATION");
|
|
15208
|
+
}
|
|
15209
|
+
headers[auth.header.toLowerCase()] = String(key);
|
|
15019
15210
|
break;
|
|
15020
15211
|
}
|
|
15021
15212
|
case "digest": {
|
|
@@ -15034,6 +15225,37 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15034
15225
|
}
|
|
15035
15226
|
return { ...req, headers };
|
|
15036
15227
|
}
|
|
15228
|
+
var CROSS_ORIGIN_STRIP_HEADERS = /* @__PURE__ */ new Set([
|
|
15229
|
+
"authorization",
|
|
15230
|
+
"cookie",
|
|
15231
|
+
"proxy-authorization",
|
|
15232
|
+
"x-api-key",
|
|
15233
|
+
"x-auth-token",
|
|
15234
|
+
"x-access-token",
|
|
15235
|
+
"x-refresh-token",
|
|
15236
|
+
"x-csrf-token",
|
|
15237
|
+
"x-session-id",
|
|
15238
|
+
"x-session-token",
|
|
15239
|
+
"x-secret",
|
|
15240
|
+
"x-secret-key",
|
|
15241
|
+
"x-private-key",
|
|
15242
|
+
"api-key",
|
|
15243
|
+
"apikey",
|
|
15244
|
+
"www-authenticate"
|
|
15245
|
+
]);
|
|
15246
|
+
function redactUserInfo(url) {
|
|
15247
|
+
try {
|
|
15248
|
+
const u = new URL(url);
|
|
15249
|
+
if (u.username || u.password) {
|
|
15250
|
+
u.username = "";
|
|
15251
|
+
u.password = "";
|
|
15252
|
+
return u.toString();
|
|
15253
|
+
}
|
|
15254
|
+
return url;
|
|
15255
|
+
} catch {
|
|
15256
|
+
return url.replace(/\/\/[^/@]*@/, "//");
|
|
15257
|
+
}
|
|
15258
|
+
}
|
|
15037
15259
|
function buildURL(base, url, params) {
|
|
15038
15260
|
const MAX_QUERY_PARAM_COUNT = 100;
|
|
15039
15261
|
const MAX_URL_LENGTH = 8192;
|
|
@@ -15054,7 +15276,7 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15054
15276
|
}
|
|
15055
15277
|
if (!params || Object.keys(params).length === 0) {
|
|
15056
15278
|
if (!isSafeURL(full)) {
|
|
15057
|
-
throw new KinetexError(`URL "${full}" failed safety check \u2014 blocked private/loopback address or forbidden scheme`, "EVALIDATION");
|
|
15279
|
+
throw new KinetexError(`URL "${redactUserInfo(full)}" failed safety check \u2014 blocked private/loopback address or forbidden scheme`, "EVALIDATION");
|
|
15058
15280
|
}
|
|
15059
15281
|
return full;
|
|
15060
15282
|
}
|
|
@@ -15088,7 +15310,7 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15088
15310
|
throw new KinetexError(`URL length ${result.length} bytes exceeds limit of ${MAX_URL_LENGTH} bytes`, "EVALIDATION");
|
|
15089
15311
|
}
|
|
15090
15312
|
if (!isSafeURL(result)) {
|
|
15091
|
-
throw new KinetexError(`URL "${result}" failed safety check \u2014 blocked private/loopback address or forbidden scheme`, "EVALIDATION");
|
|
15313
|
+
throw new KinetexError(`URL "${redactUserInfo(result)}" failed safety check \u2014 blocked private/loopback address or forbidden scheme`, "EVALIDATION");
|
|
15092
15314
|
}
|
|
15093
15315
|
return result;
|
|
15094
15316
|
} catch (err) {
|
|
@@ -15126,6 +15348,9 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15126
15348
|
if (result.length > MAX_URL_LENGTH) {
|
|
15127
15349
|
throw new KinetexError(`URL length ${result.length} bytes exceeds limit of ${MAX_URL_LENGTH} bytes`, "EVALIDATION");
|
|
15128
15350
|
}
|
|
15351
|
+
if (!isSafeURL(result)) {
|
|
15352
|
+
throw new KinetexError(`URL "${redactUserInfo(result)}" failed safety check \u2014 blocked private/loopback address or forbidden scheme`, "EVALIDATION");
|
|
15353
|
+
}
|
|
15129
15354
|
return result;
|
|
15130
15355
|
}
|
|
15131
15356
|
}
|
|
@@ -15873,6 +16098,10 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15873
16098
|
throw new KinetexError(`Invalid HTTP method '${method}'. Valid methods: ${VALID_METHODS.join(", ")}`, "EVALIDATION");
|
|
15874
16099
|
}
|
|
15875
16100
|
const fullUrl = buildURL(options.baseURL ?? this.cfg.baseURL, url, mergeParams(this.cfg.params, options.params));
|
|
16101
|
+
const proxy = options.proxy ?? this.cfg.proxy;
|
|
16102
|
+
if (proxy) {
|
|
16103
|
+
throw new KinetexError("proxy is configured but kinetex's built-in transports cannot route through it: HTTP(S) proxies require a custom fetch with a proxy agent (e.g. undici ProxyAgent passed via the `fetch` option), and SOCKS5 requires createSocks5Tunnel() from kinetex/socks5. Set up one of those instead of relying on `proxy` silently doing nothing.", "EVALIDATION");
|
|
16104
|
+
}
|
|
15876
16105
|
if (this.cfg.httpsOnly) {
|
|
15877
16106
|
try {
|
|
15878
16107
|
const parsedUrl = new URL(fullUrl);
|
|
@@ -15896,9 +16125,25 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
15896
16125
|
bodySize2 = options.body.byteLength;
|
|
15897
16126
|
} else if (options.body instanceof Blob) {
|
|
15898
16127
|
bodySize2 = options.body.size;
|
|
16128
|
+
} else if (ArrayBuffer.isView(options.body)) {
|
|
16129
|
+
bodySize2 = options.body.byteLength;
|
|
16130
|
+
} else if (options.body instanceof URLSearchParams) {
|
|
16131
|
+
bodySize2 = new TextEncoder().encode(options.body.toString()).byteLength;
|
|
15899
16132
|
} else if (options.body instanceof FormData) {
|
|
16133
|
+
const boundaryOverhead = 76;
|
|
16134
|
+
for (const [name, value] of options.body) {
|
|
16135
|
+
bodySize2 += new TextEncoder().encode(name).byteLength + boundaryOverhead;
|
|
16136
|
+
if (typeof value === "string") {
|
|
16137
|
+
bodySize2 += new TextEncoder().encode(value).byteLength;
|
|
16138
|
+
} else {
|
|
16139
|
+
bodySize2 += value.size;
|
|
16140
|
+
}
|
|
16141
|
+
}
|
|
16142
|
+
bodySize2 += boundaryOverhead;
|
|
16143
|
+
} else if (options.body instanceof ReadableStream) {
|
|
16144
|
+
throw new KinetexError(`maxRequestSize cannot be enforced for ReadableStream bodies \u2014 pass maxRequestSize: 0 to opt out, or buffer the body first`, "EVALIDATION");
|
|
15900
16145
|
} else if (options.body && typeof options.body === "object") {
|
|
15901
|
-
bodySize2 = JSON.stringify(options.body).
|
|
16146
|
+
bodySize2 = new TextEncoder().encode(JSON.stringify(options.body)).byteLength;
|
|
15902
16147
|
}
|
|
15903
16148
|
if (bodySize2 > maxRequestSize) {
|
|
15904
16149
|
throw new KinetexError(`Request body size ${bodySize2} bytes exceeds limit of ${maxRequestSize} bytes`, "EVALIDATION");
|
|
@@ -16078,10 +16323,26 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
16078
16323
|
async _sendFollowingRedirects(req, timeout, jar, appliedAuth) {
|
|
16079
16324
|
const MAX_REDIRECTS = 20;
|
|
16080
16325
|
let currentReq = { ...req, redirect: "manual" };
|
|
16326
|
+
const origin0 = (() => {
|
|
16327
|
+
try {
|
|
16328
|
+
return new URL(req.url).origin;
|
|
16329
|
+
} catch {
|
|
16330
|
+
return null;
|
|
16331
|
+
}
|
|
16332
|
+
})();
|
|
16081
16333
|
const visited = /* @__PURE__ */ new Set();
|
|
16082
16334
|
for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
|
|
16083
16335
|
if (hop > 0 && appliedAuth) {
|
|
16084
|
-
|
|
16336
|
+
const sameOrigin = (() => {
|
|
16337
|
+
try {
|
|
16338
|
+
return new URL(currentReq.url).origin === origin0;
|
|
16339
|
+
} catch {
|
|
16340
|
+
return false;
|
|
16341
|
+
}
|
|
16342
|
+
})();
|
|
16343
|
+
if (sameOrigin) {
|
|
16344
|
+
currentReq = await applyAuth(currentReq, appliedAuth);
|
|
16345
|
+
}
|
|
16085
16346
|
}
|
|
16086
16347
|
if (hop > 0 && this.cfg.hooks?.onBeforeRequest) {
|
|
16087
16348
|
for (const fn of this.cfg.hooks.onBeforeRequest) {
|
|
@@ -16153,6 +16414,14 @@ ${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
|
16153
16414
|
} else {
|
|
16154
16415
|
delete nextHeaders["cookie"];
|
|
16155
16416
|
}
|
|
16417
|
+
try {
|
|
16418
|
+
if (new URL(nextUrl).origin !== new URL(currentReq.url).origin) {
|
|
16419
|
+
for (const h of CROSS_ORIGIN_STRIP_HEADERS) {
|
|
16420
|
+
delete nextHeaders[h];
|
|
16421
|
+
}
|
|
16422
|
+
}
|
|
16423
|
+
} catch {
|
|
16424
|
+
}
|
|
16156
16425
|
currentReq = {
|
|
16157
16426
|
...currentReq,
|
|
16158
16427
|
url: nextUrl,
|