melperjs 15.0.0 → 16.0.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.
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.base64Decode = base64Decode;
7
+ exports.base64Encode = base64Encode;
8
+ exports.bcryptHash = bcryptHash;
9
+ exports.bcryptVerify = bcryptVerify;
10
+ exports.clearDirectory = clearDirectory;
11
+ exports.createNumberedDirs = createNumberedDirs;
12
+ exports.executeCommand = executeCommand;
13
+ exports.gitVersion = gitVersion;
14
+ exports.hash = hash;
15
+ exports.hostIp = hostIp;
16
+ exports.md5 = md5;
17
+ exports.normalizeProxy = normalizeProxy;
18
+ exports.parseProxy = parseProxy;
19
+ exports.proxyValue = proxyValue;
20
+ exports.readJsonFile = readJsonFile;
21
+ exports.readJsonFileSync = readJsonFileSync;
22
+ exports.secureRandomBoolean = secureRandomBoolean;
23
+ exports.secureRandomElement = secureRandomElement;
24
+ exports.secureRandomHex = secureRandomHex;
25
+ exports.secureRandomInteger = secureRandomInteger;
26
+ exports.secureRandomString = secureRandomString;
27
+ exports.secureRandomUuid = secureRandomUuid;
28
+ exports.secureRandomWeighted = secureRandomWeighted;
29
+ exports.sha256 = sha256;
30
+ exports.uuidFromSeed = uuidFromSeed;
31
+ exports.writeJsonFile = writeJsonFile;
32
+ exports.writeJsonFileSync = writeJsonFileSync;
33
+ var _fs = _interopRequireWildcard(require("fs"));
34
+ var _path = _interopRequireDefault(require("path"));
35
+ var _crypto = _interopRequireDefault(require("crypto"));
36
+ var _os = require("os");
37
+ var _child_process = require("child_process");
38
+ var _util = require("util");
39
+ var _bcryptjs = _interopRequireDefault(require("bcryptjs"));
40
+ var _index = require("./index.cjs");
41
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
42
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
43
+ const execAsync = (0, _util.promisify)(_child_process.exec);
44
+ function secureRandomBoolean() {
45
+ return _crypto.default.randomInt(2) === 0;
46
+ }
47
+ function secureRandomString(length, useNumbers = true, useUppercase = false) {
48
+ let characters = _index.CONSTANTS.LOWER_CASE;
49
+ if (useUppercase) characters += _index.CONSTANTS.UPPER_CASE;
50
+ if (useNumbers) characters += _index.CONSTANTS.NUMBERS;
51
+ let result = '';
52
+ for (let i = 0; i < length; i++) {
53
+ result += characters[_crypto.default.randomInt(0, characters.length)];
54
+ }
55
+ return result;
56
+ }
57
+ function secureRandomHex(length) {
58
+ return _crypto.default.randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length);
59
+ }
60
+ function secureRandomInteger(min, max) {
61
+ return _crypto.default.randomInt(min, max);
62
+ }
63
+ function secureRandomUuid(useDashes = true) {
64
+ const uuid = _crypto.default.randomUUID();
65
+ return useDashes ? uuid : uuid.replaceAll("-", "");
66
+ }
67
+ function secureRandomWeighted(object) {
68
+ const elements = Object.keys(object);
69
+ const weights = Object.values(object);
70
+ const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
71
+ const randomNum = secureRandomInteger(0, totalWeight);
72
+ let weightSum = 0;
73
+ for (let i = 0; i < elements.length; i++) {
74
+ weightSum += weights[i];
75
+ if (randomNum < weightSum) {
76
+ return elements[i];
77
+ }
78
+ }
79
+ }
80
+ function secureRandomElement(object) {
81
+ if (!object) return undefined;
82
+ const values = Array.isArray(object) ? object : Object.values(object);
83
+ if (values.length === 0) return undefined;
84
+ return values[_crypto.default.randomInt(0, values.length)];
85
+ }
86
+ function uuidFromSeed(seed, useDashes = true) {
87
+ const hash = _crypto.default.createHash('md5').update(seed).digest();
88
+ hash[6] = hash[6] & 0x0f | 0x30;
89
+ hash[8] = hash[8] & 0x3f | 0x80;
90
+ const hex = hash.toString('hex');
91
+ if (!useDashes) return hex;
92
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
93
+ }
94
+ function hash(algorithm, data) {
95
+ return _crypto.default.createHash(algorithm).update(data).digest("hex");
96
+ }
97
+ function md5(data) {
98
+ return hash("md5", data);
99
+ }
100
+ function sha256(data) {
101
+ return hash("sha256", data);
102
+ }
103
+ function base64Encode(data) {
104
+ return Buffer.from(data).toString('base64');
105
+ }
106
+ function base64Decode(data, encoding = 'utf8') {
107
+ return Buffer.from(data, 'base64').toString(encoding);
108
+ }
109
+ function bcryptHash(plainText, {
110
+ key = "",
111
+ strength = 12,
112
+ preHash = true
113
+ } = {}) {
114
+ let input = plainText + key;
115
+ if (preHash) {
116
+ input = sha256(input);
117
+ }
118
+ return _bcryptjs.default.hashSync(input, strength);
119
+ }
120
+ function bcryptVerify(plainText, hash, {
121
+ key = "",
122
+ preHash = true
123
+ } = {}) {
124
+ let input = plainText + key;
125
+ if (preHash) {
126
+ input = sha256(input);
127
+ }
128
+ return _bcryptjs.default.compareSync(input, hash);
129
+ }
130
+ function normalizeProxy(proxy, protocol = "http") {
131
+ proxy = proxy?.trim();
132
+ if (!proxy) return null;
133
+ const schemeMatch = proxy.match(/^([a-z][a-z0-9+.-]*):\/\/(.+)$/i);
134
+ if (schemeMatch) {
135
+ protocol = schemeMatch[1];
136
+ proxy = schemeMatch[2];
137
+ }
138
+ let auth = "";
139
+ let body = proxy;
140
+ const atIdx = body.lastIndexOf("@");
141
+ if (atIdx !== -1) {
142
+ auth = body.slice(0, atIdx) + "@";
143
+ body = body.slice(atIdx + 1);
144
+ }
145
+ if (!auth) {
146
+ // Note: when the password itself is all-digit and port-shaped (e.g. "admin:1234:host:port"),
147
+ // the heuristic cannot distinguish auth-first from host-first ordering and may pick the wrong branch.
148
+ const parts = body.split(":");
149
+ const isPort = s => /^\d+$/.test(s) && +s >= 1 && +s <= 65535;
150
+ if (parts.length === 4) {
151
+ if (isPort(parts[3]) && !isPort(parts[1])) {
152
+ // user:pass:host:port
153
+ auth = `${parts[0]}:${parts[1]}@`;
154
+ body = `${parts[2]}:${parts[3]}`;
155
+ } else {
156
+ // host:port:user:pass (default)
157
+ auth = `${parts[2]}:${parts[3]}@`;
158
+ body = `${parts[0]}:${parts[1]}`;
159
+ }
160
+ } else if (parts.length === 5) {
161
+ if (isPort(parts[3]) && isPort(parts[4]) && !isPort(parts[1])) {
162
+ // user:pass:host:portStart:portEnd
163
+ auth = `${parts[0]}:${parts[1]}@`;
164
+ body = `${parts[2]}:${parts[3]}:${parts[4]}`;
165
+ } else {
166
+ // host:portStart:portEnd:user:pass (default)
167
+ auth = `${parts[3]}:${parts[4]}@`;
168
+ body = `${parts[0]}:${parts[1]}:${parts[2]}`;
169
+ }
170
+ }
171
+ }
172
+ const parts = body.split(":");
173
+ if (parts.length === 3) {
174
+ const start = Number(parts[1]);
175
+ const end = Number(parts[2]);
176
+ if (Number.isInteger(start) && Number.isInteger(end) && start >= 0 && start <= end) {
177
+ body = `${parts[0]}:${_crypto.default.randomInt(start, end + 1)}`;
178
+ }
179
+ }
180
+ return `${protocol}://${auth}${body}`;
181
+ }
182
+ function parseProxy(proxy, protocol = "http") {
183
+ const normalized = normalizeProxy(proxy, protocol);
184
+ if (!normalized) return null;
185
+ const [scheme, rest] = normalized.split("://");
186
+ const atIdx = rest.lastIndexOf("@");
187
+ const authPart = atIdx === -1 ? null : rest.slice(0, atIdx);
188
+ const hostPart = atIdx === -1 ? rest : rest.slice(atIdx + 1);
189
+ const [host, port] = hostPart.split(":");
190
+ const result = {
191
+ protocol: scheme,
192
+ host,
193
+ port: parseInt(port, 10)
194
+ };
195
+ if (authPart !== null) {
196
+ const colonIdx = authPart.indexOf(":");
197
+ const [username, password] = colonIdx === -1 ? [authPart, ""] : [authPart.slice(0, colonIdx), authPart.slice(colonIdx + 1)];
198
+ result.auth = {
199
+ username,
200
+ password
201
+ };
202
+ }
203
+ return result;
204
+ }
205
+ function proxyValue(rawProxy, replacements = {}) {
206
+ const list = (0, _index.splitTrim)(rawProxy || "");
207
+ if (list.length === 0) return null;
208
+ const picked = list[(0, _index.randomInteger)(0, list.length)];
209
+ const {
210
+ SESSION,
211
+ ...rest
212
+ } = replacements;
213
+ let sessionValue;
214
+ if (SESSION === undefined) {
215
+ sessionValue = (0, _index.randomHex)(8);
216
+ } else if (typeof SESSION === "function") {
217
+ sessionValue = SESSION();
218
+ } else {
219
+ sessionValue = (0, _index.seedHex)(String(SESSION), 8);
220
+ }
221
+ let result = normalizeProxy(picked);
222
+ if (!result) return null;
223
+ result = result.replace("{SESSION}", sessionValue);
224
+ for (const [key, value] of Object.entries(rest)) {
225
+ const v = typeof value === "function" ? value() : String(value);
226
+ result = result.replace(`{${key}}`, v);
227
+ }
228
+ return result;
229
+ }
230
+ async function readJsonFile(filePath, defaultValue = {}) {
231
+ try {
232
+ const data = await _fs.promises.readFile(filePath, 'utf8');
233
+ return JSON.parse(data);
234
+ } catch {
235
+ return defaultValue;
236
+ }
237
+ }
238
+ function readJsonFileSync(filePath, defaultValue = {}) {
239
+ try {
240
+ const data = _fs.default.readFileSync(filePath, 'utf8');
241
+ return JSON.parse(data);
242
+ } catch {
243
+ return defaultValue;
244
+ }
245
+ }
246
+ function writeJsonFile(filePath, data) {
247
+ const jsonData = JSON.stringify(data);
248
+ return _fs.promises.writeFile(filePath, jsonData, 'utf8');
249
+ }
250
+ function writeJsonFileSync(filePath, data) {
251
+ const jsonData = JSON.stringify(data);
252
+ return _fs.default.writeFileSync(filePath, jsonData, 'utf8');
253
+ }
254
+ async function clearDirectory(directoryPath, keepDir = true) {
255
+ await _fs.promises.rm(directoryPath, {
256
+ recursive: true,
257
+ force: true
258
+ });
259
+ if (keepDir) await _fs.promises.mkdir(directoryPath, {
260
+ recursive: true
261
+ });
262
+ }
263
+ function createNumberedDirs(mainDirectory, start = 0, end = 9) {
264
+ _fs.default.mkdirSync(mainDirectory, {
265
+ recursive: true
266
+ });
267
+ for (let i = start; i <= end; i++) {
268
+ _fs.default.mkdirSync(_path.default.join(mainDirectory, `${i}`), {
269
+ recursive: true
270
+ });
271
+ }
272
+ }
273
+ async function executeCommand(command) {
274
+ const {
275
+ stdout
276
+ } = await execAsync(command);
277
+ return stdout.trim();
278
+ }
279
+ function hostIp() {
280
+ for (const list of Object.values((0, _os.networkInterfaces)())) {
281
+ for (const alias of list) {
282
+ if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.address.startsWith('192.168.') && !alias.internal) {
283
+ return alias.address;
284
+ }
285
+ }
286
+ }
287
+ return '127.0.0.1';
288
+ }
289
+ function gitVersion() {
290
+ try {
291
+ const raw = (0, _child_process.execFileSync)('git', ['show', '-s', '--format=%ct', 'HEAD'], {
292
+ encoding: 'utf8'
293
+ }).trim();
294
+ const timestamp = parseInt(raw, 10);
295
+ if (isNaN(timestamp)) return "1.0";
296
+ const iso = new Date(timestamp * 1000).toISOString();
297
+ return `${iso.slice(2, 4)}${iso.slice(5, 7)}${iso.slice(8, 10)}.${iso.slice(11, 13)}${iso.slice(14, 16)}`;
298
+ } catch {
299
+ return "1.0";
300
+ }
301
+ }
@@ -0,0 +1,306 @@
1
+ import xss from "xss";
2
+ import setCookieParser from "set-cookie-parser";
3
+ import camelCase from "lodash/camelCase.js";
4
+ import upperFirst from "lodash/upperFirst.js";
5
+ import isEmpty from "lodash/isEmpty.js";
6
+ import shuffle from "lodash/shuffle.js";
7
+ export const CONSTANTS = {
8
+ LOWER_CASE: "abcdefghijklmnopqrstuvwxyz",
9
+ UPPER_CASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
10
+ HEXADECIMAL: "0123456789abcdef",
11
+ NUMBERS: "0123456789",
12
+ INT32_MIN: -2147483648,
13
+ INT32_MAX: 2147483647
14
+ };
15
+ const NUMBER_PATTERN = /^-?\d+(\.\d+)?(e[+-]?\d+)?$/i;
16
+ const INTEGER_PATTERN = /^-?\d+$/;
17
+ export function Exception(message, response = {}, name = null) {
18
+ const error = new Error(message);
19
+ error.name = name || "Exception";
20
+ error.response = response;
21
+ if (checkEmpty(response)) {
22
+ error.response = {};
23
+ }
24
+ return error;
25
+ }
26
+ export function time() {
27
+ return Math.floor(Date.now() / 1000);
28
+ }
29
+ export function sleepMs(milliseconds) {
30
+ return new Promise(resolve => setTimeout(resolve, milliseconds));
31
+ }
32
+ export function sleep(seconds) {
33
+ return sleepMs(seconds * 1000);
34
+ }
35
+ export function promiseTimeout(milliseconds, promise) {
36
+ let timer;
37
+ const timeout = new Promise((_, reject) => {
38
+ timer = setTimeout(() => reject(new Error(`Promise timed out after ${milliseconds}ms`)), milliseconds);
39
+ });
40
+ return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
41
+ }
42
+ export function promiseSilent(promise) {
43
+ return promise.then(() => {}).catch(() => {});
44
+ }
45
+ export async function forever(delayMs, task, onError = null, onFinally = null) {
46
+ if (!isPositiveNumber(delayMs)) throw new Error("delayMs must be a positive number");
47
+ const maybeUpdate = value => {
48
+ if (isPositiveNumber(value)) delayMs = value;
49
+ };
50
+ while (true) {
51
+ try {
52
+ maybeUpdate(await task());
53
+ } catch (error) {
54
+ if (onError) maybeUpdate(await onError(error));
55
+ } finally {
56
+ if (onFinally) {
57
+ try {
58
+ maybeUpdate(await onFinally());
59
+ } catch {}
60
+ }
61
+ await sleepMs(delayMs);
62
+ }
63
+ }
64
+ }
65
+ export async function retry(callFn, maxAttempts, errorFn = null, {
66
+ delayMs = 0,
67
+ backoffFactor = 1
68
+ } = {}) {
69
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
70
+ try {
71
+ return await callFn();
72
+ } catch (error) {
73
+ if (errorFn) await errorFn(attempt, error);
74
+ if (attempt >= maxAttempts) throw error;
75
+ if (delayMs > 0) await sleepMs(delayMs * backoffFactor ** (attempt - 1));
76
+ }
77
+ }
78
+ }
79
+ export function isValidURL(url) {
80
+ try {
81
+ new URL(url);
82
+ return true;
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+ export function splitTrim(string, separator = null) {
88
+ return string.split(separator ?? /\r?\n/).map(item => item.trim()).filter(Boolean);
89
+ }
90
+ export function checkEmpty(value) {
91
+ if (typeof value === "number") return value === 0;
92
+ return isEmpty(value);
93
+ }
94
+ export function pascalCase(string) {
95
+ return upperFirst(camelCase(string));
96
+ }
97
+ export function titleCase(string, separator = " ") {
98
+ return (string || "").split(separator).map(upperFirst).join(separator);
99
+ }
100
+ export function isInt32(value) {
101
+ return Number.isInteger(value) && value >= CONSTANTS.INT32_MIN && value <= CONSTANTS.INT32_MAX;
102
+ }
103
+ export function isPositiveNumber(value) {
104
+ return typeof value === 'number' && Number.isFinite(value) && value > 0;
105
+ }
106
+ export function coerceObjectNumbers(object) {
107
+ for (const key of Object.keys(object)) {
108
+ const value = object[key];
109
+ if (typeof value === 'string' && NUMBER_PATTERN.test(value)) {
110
+ object[key] = parseFloat(value);
111
+ }
112
+ }
113
+ return object;
114
+ }
115
+ export function coerceObjectIntegers(object) {
116
+ for (const key of Object.keys(object)) {
117
+ const value = object[key];
118
+ if (typeof value === 'string' && INTEGER_PATTERN.test(value)) {
119
+ object[key] = parseInt(value);
120
+ }
121
+ }
122
+ return object;
123
+ }
124
+ export function findNodeByKey(key, node, pair = null) {
125
+ if (node && typeof node === 'object') {
126
+ if (Object.hasOwn(node, key) && (pair === null || node[key] === pair)) {
127
+ return node;
128
+ }
129
+ for (const childKey of Object.keys(node)) {
130
+ const result = findNodeByKey(key, node[childKey], pair);
131
+ if (result) return result;
132
+ }
133
+ }
134
+ return null;
135
+ }
136
+ export function waitForProperty(object, property, timeout = 5000, interval = 100) {
137
+ return new Promise((resolve, reject) => {
138
+ if (Object.hasOwn(object, property)) {
139
+ resolve(object[property]);
140
+ return;
141
+ }
142
+ const startTime = Date.now();
143
+ const checkProperty = setInterval(() => {
144
+ if (Object.hasOwn(object, property)) {
145
+ clearInterval(checkProperty);
146
+ resolve(object[property]);
147
+ } else if (Date.now() - startTime >= timeout) {
148
+ clearInterval(checkProperty);
149
+ reject(new Error(`Property "${property}" did not appear within ${timeout} milliseconds`));
150
+ }
151
+ }, interval);
152
+ });
153
+ }
154
+ export function shuffleObject(object) {
155
+ return Object.fromEntries(shuffle(Object.entries(object)));
156
+ }
157
+ export function objectStringify(object) {
158
+ for (const key of Object.keys(object)) {
159
+ const value = object[key];
160
+ if (value !== null && typeof value === 'object') {
161
+ objectStringify(value);
162
+ } else {
163
+ object[key] = String(value);
164
+ }
165
+ }
166
+ return object;
167
+ }
168
+ export function limitString(string, limit = 35, omission = "...") {
169
+ string = string || "";
170
+ if (string.length <= limit) return string;
171
+ return string.slice(0, limit - omission.length) + omission;
172
+ }
173
+ export function safeString(string) {
174
+ return xss(string || "", {
175
+ whiteList: {},
176
+ stripIgnoreTag: true,
177
+ stripIgnoreTagBody: ["script", "style", "iframe", "object", "embed", "form"],
178
+ css: false
179
+ });
180
+ }
181
+ export function shuffleString(string) {
182
+ return shuffle(string.split('')).join('');
183
+ }
184
+ export function randomBoolean() {
185
+ return Math.random() < 0.5;
186
+ }
187
+ export function randomString(length, useNumbers = true, useUppercase = false) {
188
+ let characters = CONSTANTS.LOWER_CASE;
189
+ if (useUppercase) characters += CONSTANTS.UPPER_CASE;
190
+ if (useNumbers) characters += CONSTANTS.NUMBERS;
191
+ let result = '';
192
+ for (let i = 0; i < length; i++) {
193
+ result += characters[Math.random() * characters.length | 0];
194
+ }
195
+ return result;
196
+ }
197
+ export function randomHex(length) {
198
+ let result = '';
199
+ for (let i = 0; i < length; i++) {
200
+ result += CONSTANTS.HEXADECIMAL[Math.random() * 16 | 0];
201
+ }
202
+ return result;
203
+ }
204
+ export function randomInteger(min, max) {
205
+ if (typeof max === 'undefined') {
206
+ max = min;
207
+ min = 0;
208
+ }
209
+ if (typeof min !== 'number' || typeof max !== 'number') {
210
+ throw new Error('min and max must be numerical values');
211
+ }
212
+ if (max <= min) {
213
+ throw new Error('max must be greater than min');
214
+ }
215
+ return Math.floor(Math.random() * (max - min)) + min;
216
+ }
217
+ export function randomUuid(useDashes = true) {
218
+ const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
219
+ const r = Math.random() * 16 | 0;
220
+ return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
221
+ });
222
+ return useDashes ? uuid : uuid.replaceAll("-", "");
223
+ }
224
+ export function randomWeighted(object) {
225
+ const elements = Object.keys(object);
226
+ const weights = Object.values(object);
227
+ const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
228
+ const randomNum = Math.random() * totalWeight;
229
+ let weightSum = 0;
230
+ for (let i = 0; i < elements.length; i++) {
231
+ weightSum += weights[i];
232
+ if (randomNum < weightSum) {
233
+ return elements[i];
234
+ }
235
+ }
236
+ }
237
+ export function randomElement(object) {
238
+ if (!object) return undefined;
239
+ const values = Array.isArray(object) ? object : Object.values(object);
240
+ if (values.length === 0) return undefined;
241
+ return values[Math.floor(Math.random() * values.length)];
242
+ }
243
+ export function mulberry32(seed) {
244
+ if (typeof seed === "string") {
245
+ let h = 0;
246
+ for (let i = 0; i < seed.length; i++) {
247
+ h = Math.imul(h ^ seed.charCodeAt(i), 2654435761);
248
+ }
249
+ seed = h >>> 0;
250
+ }
251
+ return function () {
252
+ seed = seed + 0x6D2B79F5 | 0;
253
+ let t = seed;
254
+ t = Math.imul(t ^ t >>> 15, t | 1);
255
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
256
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
257
+ };
258
+ }
259
+ export function seedHex(seed, length) {
260
+ const rng = mulberry32(String(seed));
261
+ let result = '';
262
+ while (result.length < length) {
263
+ result += Math.floor(rng() * 0x100000000).toString(16).padStart(8, '0');
264
+ }
265
+ return result.slice(0, length);
266
+ }
267
+ export function cookiesFromResponse(response, decodeValues = false) {
268
+ const dict = {};
269
+ const cookies = setCookieParser.parse(response, {
270
+ decodeValues
271
+ });
272
+ for (const cookie of cookies) {
273
+ dict[cookie.name] = cookie.value;
274
+ }
275
+ return dict;
276
+ }
277
+ export function cookiesToHeader(cookies) {
278
+ if (!cookies) return "";
279
+ return Object.entries(cookies).filter(([, value]) => value !== null && value !== undefined).map(([key, value]) => `${key}=${value}`).join("; ");
280
+ }
281
+ export function cookiesFromHeader(header) {
282
+ const cookies = {};
283
+ if (!header) return cookies;
284
+ header.split(';').forEach(cookie => {
285
+ const trimmed = cookie.trim();
286
+ if (!trimmed.includes('=')) return;
287
+ const [key, ...valueParts] = trimmed.split('=');
288
+ const trimmedKey = key.trim();
289
+ if (trimmedKey) {
290
+ cookies[trimmedKey] = valueParts.join('=').trim();
291
+ }
292
+ });
293
+ return cookies;
294
+ }
295
+ export function isTransientHttpCode(httpCode) {
296
+ return !httpCode || isNaN(httpCode) || httpCode === 100 || httpCode === 402 || httpCode === 407 || 460 <= httpCode && httpCode < 470 || 500 <= httpCode;
297
+ }
298
+ export function getResponseError(error, limit = 200) {
299
+ let response;
300
+ if (error?.response?.status && error.response.data) {
301
+ response = `${error.response.status}|${error.response.data}`;
302
+ } else if (error?.response?.data) {
303
+ response = error.response.data;
304
+ }
305
+ return limitString(response || error.message, limit).trim();
306
+ }