melperjs 17.0.0 → 17.1.1

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.
@@ -114,7 +114,7 @@ Splits a string, trims each piece, and drops empty results. Default separator is
114
114
 
115
115
  ### pascalCase(string)
116
116
 
117
- Converts arbitrary text to `PascalCase` (uses lodash internally).
117
+ Converts arbitrary text to `PascalCase` (uses es-toolkit internally).
118
118
 
119
119
  - **Parameters:**
120
120
  - `string` (String): Input text.
@@ -149,7 +149,7 @@ Strips HTML tags via the `xss` library and additionally removes the body of dang
149
149
 
150
150
  ### shuffleString(string)
151
151
 
152
- Randomly reorders the characters in a string using lodash's `shuffle` (Fisher-Yates).
152
+ Randomly reorders the characters in a string using es-toolkit's `shuffle` (Fisher-Yates).
153
153
 
154
154
  - **Parameters:**
155
155
  - `string` (String): Source string.
@@ -238,7 +238,7 @@ Builds a deterministic hex string of the requested length from a seed via `mulbe
238
238
 
239
239
  ### checkEmpty(value)
240
240
 
241
- Like lodash's `isEmpty` but additionally treats `0` (numeric zero) as empty.
241
+ Like es-toolkit's `isEmpty` but additionally treats `0` (numeric zero) as empty.
242
242
 
243
243
  - **Parameters:**
244
244
  - `value` (Any): Value to test.
@@ -288,17 +288,17 @@ Depth-first search through a nested object for the first node that owns `key`. I
288
288
  - `pair` (Any): Optional value constraint. `null` means "match any value".
289
289
  - **Returns:** The matching node, or `null` if not found.
290
290
 
291
- ### waitForProperty(object, property, timeout, interval = 100)
291
+ ### waitForProperty(object, property, timeoutMs, interval = 100)
292
292
 
293
293
  Polls `object` until it owns `property`, then resolves with the property's value. Rejects after `timeout` milliseconds.
294
294
 
295
295
  - **Parameters:**
296
296
  - `object` (Object): Object to watch.
297
297
  - `property` (String): Property name to wait for.
298
- - `timeout` (Number): Maximum wait time in milliseconds.
298
+ - `timeoutMs` (Number): Maximum wait time in milliseconds.
299
299
  - `interval` (Number): Poll interval in milliseconds.
300
300
  - **Returns:** `Promise` resolving to the property's value.
301
- - **Throws:** When the property does not appear within `timeout`.
301
+ - **Throws:** When the property does not appear within `timeoutMs`.
302
302
 
303
303
  ### shuffleObject(object)
304
304
 
package/docs/node.md CHANGED
@@ -7,7 +7,7 @@ and will not run in a browser.
7
7
 
8
8
  All `secureRandom*` helpers use Node's `crypto` module (`crypto.randomInt`, `crypto.randomBytes`, `crypto.randomUUID`).
9
9
  Use these for session tokens, API keys, nonces, and anything security-sensitive. For non-secure / faster equivalents,
10
- see the `random*` family in [General Functions](index.md).
10
+ see the `random*` family in [General Functions](general.md).
11
11
 
12
12
  ### secureRandomBoolean()
13
13
 
package/package.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "melperjs",
3
+ "version": "17.1.1",
3
4
  "description": "A compact JavaScript utility library for strings, objects, tokens, hashing, cookies, proxies, file I/O, shell, and more.",
4
5
  "keywords": [
5
6
  "melperjs",
@@ -24,51 +25,51 @@
24
25
  "file-system",
25
26
  "shell"
26
27
  ],
28
+ "homepage": "https://github.com/mahelbir/melperjs#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/mahelbir/melperjs/issues"
31
+ },
27
32
  "repository": {
28
33
  "type": "git",
29
34
  "url": "git+https://github.com/mahelbir/melperjs.git"
30
35
  },
31
- "author": "Mahmuthan Elbir",
32
36
  "license": "MIT",
37
+ "author": "Mahmuthan Elbir",
33
38
  "type": "module",
34
- "files": [
35
- "lib/**/*",
36
- "docs/**/*"
37
- ],
38
- "private": false,
39
- "publishConfig": {
40
- "access": "public"
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
41
  },
42
+ "sideEffects": false,
42
43
  "exports": {
43
44
  ".": {
44
- "import": "./lib/esm/index.mjs",
45
- "require": "./lib/cjs/index.cjs"
45
+ "import": "./dist/general.mjs",
46
+ "require": "./dist/general.cjs"
46
47
  },
47
48
  "./node": {
48
- "import": "./lib/esm/node.mjs",
49
- "require": "./lib/cjs/node.cjs"
49
+ "import": "./dist/node.mjs",
50
+ "require": "./dist/node.cjs"
50
51
  }
51
52
  },
53
+ "files": [
54
+ "dist/**/*",
55
+ "docs/**/*"
56
+ ],
52
57
  "scripts": {
53
- "build:esm": "npx cross-env BABEL_ENV=esm babel ./src --out-dir ./lib/esm --out-file-extension .mjs",
54
- "build:cjs": "npx cross-env BABEL_ENV=cjs babel ./src --out-dir ./lib/cjs --out-file-extension .cjs",
55
- "build": "npm run build:esm && npm run build:cjs",
56
- "test": "node --test 'tests/**/*.test.js'",
57
- "prepublishOnly": "npm run build && npm test"
58
+ "build": "tsdown",
59
+ "test": "node --test",
60
+ "prepublishOnly": "npm run build && npm test",
61
+ "relock": "rm -rf node_modules package-lock.json && NODE_ENV= npm install --include=dev --include=optional"
58
62
  },
59
63
  "dependencies": {
60
64
  "bcryptjs": "^3.0.3",
61
- "lodash": "4.18.1",
65
+ "es-toolkit": "^1.47.0",
62
66
  "set-cookie-parser": "^3.1.0",
63
67
  "xss": "^1.0.15"
64
68
  },
65
69
  "devDependencies": {
66
- "@babel/cli": "^7.28.6",
67
- "@babel/core": "^7.29.0",
68
- "@babel/preset-env": "^7.29.5",
69
- "babel-plugin-replace-import-extension": "^1.1.5",
70
- "babel-plugin-transform-import-meta": "^2.3.3",
71
- "cross-env": "^10.1.0"
70
+ "tsdown": "^0.22.2"
72
71
  },
73
- "version": "17.0.0"
72
+ "publishConfig": {
73
+ "access": "public"
74
+ }
74
75
  }
package/lib/cjs/index.cjs DELETED
@@ -1,474 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.CONSTANTS = void 0;
7
- exports.Exception = Exception;
8
- exports.checkEmpty = checkEmpty;
9
- exports.coerceObjectIntegers = coerceObjectIntegers;
10
- exports.coerceObjectNumbers = coerceObjectNumbers;
11
- exports.cookiesFromHeader = cookiesFromHeader;
12
- exports.cookiesFromResponse = cookiesFromResponse;
13
- exports.cookiesToHeader = cookiesToHeader;
14
- exports.findNodeByKey = findNodeByKey;
15
- exports.forever = forever;
16
- exports.getResponseError = getResponseError;
17
- exports.isInt32 = isInt32;
18
- exports.isPositiveNumber = isPositiveNumber;
19
- exports.isTransientHttpCode = isTransientHttpCode;
20
- exports.isValidURL = isValidURL;
21
- exports.limitString = limitString;
22
- exports.mulberry32 = mulberry32;
23
- exports.normalizeProxy = normalizeProxy;
24
- exports.objectStringify = objectStringify;
25
- exports.parseProxy = parseProxy;
26
- exports.pascalCase = pascalCase;
27
- exports.promiseSilent = promiseSilent;
28
- exports.promiseTimeout = promiseTimeout;
29
- exports.proxyValue = proxyValue;
30
- exports.randomBoolean = randomBoolean;
31
- exports.randomElement = randomElement;
32
- exports.randomHex = randomHex;
33
- exports.randomInteger = randomInteger;
34
- exports.randomString = randomString;
35
- exports.randomUuid = randomUuid;
36
- exports.randomWeighted = randomWeighted;
37
- exports.retry = retry;
38
- exports.safeString = safeString;
39
- exports.seedHex = seedHex;
40
- exports.shuffleObject = shuffleObject;
41
- exports.shuffleString = shuffleString;
42
- exports.sleep = sleep;
43
- exports.sleepMs = sleepMs;
44
- exports.splitTrim = splitTrim;
45
- exports.time = time;
46
- exports.titleCase = titleCase;
47
- exports.waitForProperty = waitForProperty;
48
- var _xss = _interopRequireDefault(require("xss"));
49
- var _setCookieParser = _interopRequireDefault(require("set-cookie-parser"));
50
- var _camelCase = _interopRequireDefault(require("lodash/camelCase.js"));
51
- var _upperFirst = _interopRequireDefault(require("lodash/upperFirst.js"));
52
- var _isEmpty = _interopRequireDefault(require("lodash/isEmpty.js"));
53
- var _shuffle = _interopRequireDefault(require("lodash/shuffle.js"));
54
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
55
- const CONSTANTS = exports.CONSTANTS = {
56
- LOWER_CASE: "abcdefghijklmnopqrstuvwxyz",
57
- UPPER_CASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
58
- HEXADECIMAL: "0123456789abcdef",
59
- NUMBERS: "0123456789",
60
- INT32_MIN: -2147483648,
61
- INT32_MAX: 2147483647
62
- };
63
- const NUMBER_PATTERN = /^-?\d+(\.\d+)?(e[+-]?\d+)?$/i;
64
- const INTEGER_PATTERN = /^-?\d+$/;
65
- function Exception(message, response = {}, name = null) {
66
- const error = new Error(message);
67
- error.name = name || "Exception";
68
- error.response = response;
69
- if (checkEmpty(response)) {
70
- error.response = {};
71
- }
72
- return error;
73
- }
74
- function time() {
75
- return Math.floor(Date.now() / 1000);
76
- }
77
- function sleepMs(milliseconds) {
78
- return new Promise(resolve => setTimeout(resolve, milliseconds));
79
- }
80
- function sleep(seconds) {
81
- return sleepMs(seconds * 1000);
82
- }
83
- function promiseTimeout(milliseconds, promise) {
84
- let timer;
85
- const timeout = new Promise((_, reject) => {
86
- timer = setTimeout(() => reject(new Error(`Promise timed out after ${milliseconds}ms`)), milliseconds);
87
- });
88
- return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
89
- }
90
- function promiseSilent(promise) {
91
- return promise.then(() => {}).catch(() => {});
92
- }
93
- async function forever(delayMs, task, onError = null, onFinally = null) {
94
- if (!isPositiveNumber(delayMs)) throw new Error("delayMs must be a positive number");
95
- const update = value => {
96
- if (isPositiveNumber(value)) delayMs = value;
97
- };
98
- while (true) {
99
- try {
100
- update(await task());
101
- } catch (error) {
102
- if (onError) update(await onError(error));
103
- } finally {
104
- if (onFinally) {
105
- try {
106
- update(await onFinally());
107
- } catch {}
108
- }
109
- await sleepMs(delayMs);
110
- }
111
- }
112
- }
113
- async function retry(task, maxAttempts = 1, onError = null, {
114
- delayMs = 0,
115
- backoffFactor = 1
116
- } = {}) {
117
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
118
- try {
119
- return await task();
120
- } catch (error) {
121
- if (onError) await onError(error, attempt);
122
- if (attempt >= maxAttempts) throw error;
123
- if (delayMs > 0) await sleepMs(delayMs * backoffFactor ** (attempt - 1));
124
- }
125
- }
126
- }
127
- function isValidURL(url) {
128
- try {
129
- new URL(url);
130
- return true;
131
- } catch {
132
- return false;
133
- }
134
- }
135
- function splitTrim(string, separator = null) {
136
- return string.split(separator ?? /\r?\n/).map(item => item.trim()).filter(Boolean);
137
- }
138
- function checkEmpty(value) {
139
- if (typeof value === "number") return value === 0;
140
- return (0, _isEmpty.default)(value);
141
- }
142
- function pascalCase(string) {
143
- return (0, _upperFirst.default)((0, _camelCase.default)(string));
144
- }
145
- function titleCase(string, separator = " ") {
146
- return (string || "").split(separator).map(_upperFirst.default).join(separator);
147
- }
148
- function isInt32(value) {
149
- return Number.isInteger(value) && value >= CONSTANTS.INT32_MIN && value <= CONSTANTS.INT32_MAX;
150
- }
151
- function isPositiveNumber(value) {
152
- return Number.isFinite(value) && value > 0;
153
- }
154
- function coerceObjectNumbers(object) {
155
- for (const key of Object.keys(object)) {
156
- const value = object[key];
157
- if (typeof value === 'string' && NUMBER_PATTERN.test(value)) {
158
- object[key] = parseFloat(value);
159
- }
160
- }
161
- return object;
162
- }
163
- function coerceObjectIntegers(object) {
164
- for (const key of Object.keys(object)) {
165
- const value = object[key];
166
- if (typeof value === 'string' && INTEGER_PATTERN.test(value)) {
167
- object[key] = parseInt(value);
168
- }
169
- }
170
- return object;
171
- }
172
- function findNodeByKey(key, node, pair = null) {
173
- if (node && typeof node === 'object') {
174
- if (Object.hasOwn(node, key) && (pair === null || node[key] === pair)) {
175
- return node;
176
- }
177
- for (const childKey of Object.keys(node)) {
178
- const result = findNodeByKey(key, node[childKey], pair);
179
- if (result) return result;
180
- }
181
- }
182
- return null;
183
- }
184
- function waitForProperty(object, property, timeout, interval = 100) {
185
- return new Promise((resolve, reject) => {
186
- if (Object.hasOwn(object, property)) {
187
- resolve(object[property]);
188
- return;
189
- }
190
- const startTime = Date.now();
191
- const checkProperty = setInterval(() => {
192
- if (Object.hasOwn(object, property)) {
193
- clearInterval(checkProperty);
194
- resolve(object[property]);
195
- } else if (Date.now() - startTime >= timeout) {
196
- clearInterval(checkProperty);
197
- reject(new Error(`Property "${property}" did not appear within ${timeout}ms`));
198
- }
199
- }, interval);
200
- });
201
- }
202
- function shuffleObject(object) {
203
- return Object.fromEntries((0, _shuffle.default)(Object.entries(object)));
204
- }
205
- function objectStringify(object) {
206
- for (const key of Object.keys(object)) {
207
- const value = object[key];
208
- if (value !== null && typeof value === 'object') {
209
- objectStringify(value);
210
- } else {
211
- object[key] = String(value);
212
- }
213
- }
214
- return object;
215
- }
216
- function limitString(string, limit = 35, omission = "...") {
217
- string = string || "";
218
- if (string.length <= limit) return string;
219
- return string.slice(0, limit - omission.length) + omission;
220
- }
221
- function safeString(string) {
222
- return (0, _xss.default)(string || "", {
223
- whiteList: {},
224
- stripIgnoreTag: true,
225
- stripIgnoreTagBody: ["script", "style", "iframe", "object", "embed", "form"],
226
- css: false
227
- });
228
- }
229
- function shuffleString(string) {
230
- return (0, _shuffle.default)(string.split('')).join('');
231
- }
232
- function randomBoolean() {
233
- return Math.random() < 0.5;
234
- }
235
- function randomString(length, useNumbers = true, useUppercase = false) {
236
- let characters = CONSTANTS.LOWER_CASE;
237
- if (useUppercase) characters += CONSTANTS.UPPER_CASE;
238
- if (useNumbers) characters += CONSTANTS.NUMBERS;
239
- let result = '';
240
- for (let i = 0; i < length; i++) {
241
- result += characters[Math.random() * characters.length | 0];
242
- }
243
- return result;
244
- }
245
- function randomHex(length) {
246
- let result = '';
247
- for (let i = 0; i < length; i++) {
248
- result += CONSTANTS.HEXADECIMAL[Math.random() * 16 | 0];
249
- }
250
- return result;
251
- }
252
- function randomInteger(min, max = undefined) {
253
- if (typeof max === 'undefined') {
254
- max = min;
255
- min = 0;
256
- }
257
- if (typeof min !== 'number' || typeof max !== 'number') {
258
- throw new Error('min and max must be numerical values');
259
- }
260
- if (max <= min) {
261
- throw new Error('max must be greater than min');
262
- }
263
- return Math.floor(Math.random() * (max - min)) + min;
264
- }
265
- function randomUuid(useDashes = true) {
266
- const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
267
- const r = Math.random() * 16 | 0;
268
- return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
269
- });
270
- return useDashes ? uuid : uuid.replaceAll("-", "");
271
- }
272
- function randomWeighted(object) {
273
- if (checkEmpty(object)) return undefined;
274
- const elements = Object.keys(object);
275
- const weights = Object.values(object);
276
- const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
277
- const randomNum = Math.random() * totalWeight;
278
- let weightSum = 0;
279
- for (let i = 0; i < elements.length; i++) {
280
- weightSum += weights[i];
281
- if (randomNum < weightSum) {
282
- return elements[i];
283
- }
284
- }
285
- }
286
- function randomElement(object) {
287
- if (checkEmpty(object)) return undefined;
288
- const values = Array.isArray(object) ? object : Object.values(object);
289
- if (values.length === 0) return undefined;
290
- return values[Math.floor(Math.random() * values.length)];
291
- }
292
- function mulberry32(seed) {
293
- if (typeof seed === "string") {
294
- let h = 0;
295
- for (let i = 0; i < seed.length; i++) {
296
- h = Math.imul(h ^ seed.charCodeAt(i), 2654435761);
297
- }
298
- seed = h >>> 0;
299
- }
300
- return function () {
301
- seed = seed + 0x6D2B79F5 | 0;
302
- let t = seed;
303
- t = Math.imul(t ^ t >>> 15, t | 1);
304
- t ^= t + Math.imul(t ^ t >>> 7, t | 61);
305
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
306
- };
307
- }
308
- function seedHex(seed, length) {
309
- const rng = mulberry32(String(seed));
310
- let result = '';
311
- while (result.length < length) {
312
- result += Math.floor(rng() * 0x100000000).toString(16).padStart(8, '0');
313
- }
314
- return result.slice(0, length);
315
- }
316
- function cookiesFromResponse(response, decodeValues = false) {
317
- const obj = {};
318
- const cookies = _setCookieParser.default.parse(response, {
319
- decodeValues
320
- });
321
- for (const cookie of cookies) {
322
- obj[cookie.name] = cookie.value;
323
- }
324
- return obj;
325
- }
326
- function cookiesToHeader(cookies) {
327
- if (!cookies) return "";
328
- return Object.entries(cookies).filter(([, value]) => value !== null && value !== undefined).map(([key, value]) => `${key}=${value}`).join("; ");
329
- }
330
- function cookiesFromHeader(header) {
331
- const cookies = {};
332
- if (!header) return cookies;
333
- header.split(';').forEach(cookie => {
334
- const trimmed = cookie.trim();
335
- if (!trimmed.includes('=')) return;
336
- const [key, ...valueParts] = trimmed.split('=');
337
- const trimmedKey = key.trim();
338
- if (trimmedKey) {
339
- cookies[trimmedKey] = valueParts.join('=').trim();
340
- }
341
- });
342
- return cookies;
343
- }
344
- function isTransientHttpCode(httpCode) {
345
- return !httpCode || isNaN(httpCode) || httpCode === 100 || httpCode === 402 || httpCode === 407 || 460 <= httpCode && httpCode < 470 || 500 <= httpCode;
346
- }
347
- function getResponseError(error, limit = 200) {
348
- let response;
349
- if (error?.response?.status && error.response.data) {
350
- response = `${error.response.status}|${error.response.data}`;
351
- } else if (error?.response?.data) {
352
- response = error.response.data;
353
- }
354
- return limitString(response || error.message, limit).trim();
355
- }
356
- function normalizeProxy(proxy, protocol = "http") {
357
- proxy = proxy?.trim();
358
- if (!proxy) return null;
359
- const schemeMatch = proxy.match(/^([a-z][a-z0-9+.-]*):\/\/(.+)$/i);
360
- if (schemeMatch) {
361
- protocol = schemeMatch[1];
362
- proxy = schemeMatch[2];
363
- }
364
- let auth = "";
365
- let body = proxy;
366
- const atIdx = body.lastIndexOf("@");
367
- if (atIdx !== -1) {
368
- auth = body.slice(0, atIdx) + "@";
369
- body = body.slice(atIdx + 1);
370
- }
371
- if (!auth) {
372
- /* Note: when host is single-token (e.g. "localhost") AND password is all-digit port-shaped,
373
- the heuristic stays ambiguous; prefer `user:pass@host:port` for those cases. */
374
- const parts = body.split(":");
375
- const isPort = s => /^\d+$/.test(s) && +s >= 1 && +s <= 65535;
376
- const isHost = s => s.includes(".") || /[a-z]/i.test(s);
377
- if (parts.length === 4) {
378
- if (isPort(parts[3]) && !isPort(parts[1])) {
379
- // user:pass:host:port
380
- auth = `${parts[0]}:${parts[1]}@`;
381
- body = `${parts[2]}:${parts[3]}`;
382
- } else if (isPort(parts[1]) && !isPort(parts[3])) {
383
- // host:port:user:pass
384
- auth = `${parts[2]}:${parts[3]}@`;
385
- body = `${parts[0]}:${parts[1]}`;
386
- } else if (isHost(parts[2]) && !isHost(parts[0])) {
387
- // user:pass:host:port (ambiguous; host detected at parts[2])
388
- auth = `${parts[0]}:${parts[1]}@`;
389
- body = `${parts[2]}:${parts[3]}`;
390
- } else {
391
- // host:port:user:pass (ambiguous fallback)
392
- auth = `${parts[2]}:${parts[3]}@`;
393
- body = `${parts[0]}:${parts[1]}`;
394
- }
395
- } else if (parts.length === 5) {
396
- if (isPort(parts[3]) && isPort(parts[4]) && !isPort(parts[1])) {
397
- // user:pass:host:portStart:portEnd
398
- auth = `${parts[0]}:${parts[1]}@`;
399
- body = `${parts[2]}:${parts[3]}:${parts[4]}`;
400
- } else if (isPort(parts[1]) && isPort(parts[2]) && !isPort(parts[3])) {
401
- // host:portStart:portEnd:user:pass
402
- auth = `${parts[3]}:${parts[4]}@`;
403
- body = `${parts[0]}:${parts[1]}:${parts[2]}`;
404
- } else if (isHost(parts[2]) && !isHost(parts[0])) {
405
- // user:pass:host:portStart:portEnd (ambiguous; host detected at parts[2])
406
- auth = `${parts[0]}:${parts[1]}@`;
407
- body = `${parts[2]}:${parts[3]}:${parts[4]}`;
408
- } else {
409
- // host:portStart:portEnd:user:pass (ambiguous fallback)
410
- auth = `${parts[3]}:${parts[4]}@`;
411
- body = `${parts[0]}:${parts[1]}:${parts[2]}`;
412
- }
413
- }
414
- }
415
- const parts = body.split(":");
416
- if (parts.length === 3) {
417
- const start = Number(parts[1]);
418
- const end = Number(parts[2]);
419
- if (Number.isInteger(start) && Number.isInteger(end) && start >= 0 && start <= end) {
420
- body = `${parts[0]}:${randomInteger(start, end + 1)}`;
421
- }
422
- }
423
- return `${protocol}://${auth}${body}`;
424
- }
425
- function parseProxy(proxy, protocol = "http") {
426
- const normalized = normalizeProxy(proxy, protocol);
427
- if (!normalized) return null;
428
- const [scheme, rest] = normalized.split("://");
429
- const atIdx = rest.lastIndexOf("@");
430
- const authPart = atIdx === -1 ? null : rest.slice(0, atIdx);
431
- const hostPart = atIdx === -1 ? rest : rest.slice(atIdx + 1);
432
- const [host, port] = hostPart.split(":");
433
- const result = {
434
- protocol: scheme,
435
- host,
436
- port: parseInt(port, 10)
437
- };
438
- if (authPart !== null) {
439
- const colonIdx = authPart.indexOf(":");
440
- const [username, password] = colonIdx === -1 ? [authPart, ""] : [authPart.slice(0, colonIdx), authPart.slice(colonIdx + 1)];
441
- result.auth = {
442
- username,
443
- password
444
- };
445
- }
446
- return result;
447
- }
448
- function proxyValue(rawProxy, replacements = {}) {
449
- const list = splitTrim(rawProxy || "");
450
- if (list.length === 0) return null;
451
- const picked = list[randomInteger(0, list.length)];
452
- let result = normalizeProxy(picked);
453
- if (!result) return null;
454
- if (result.includes("{")) {
455
- const {
456
- SESSION,
457
- ...rest
458
- } = replacements;
459
- let sessionValue;
460
- if (SESSION === undefined) {
461
- sessionValue = randomHex(8);
462
- } else if (typeof SESSION === "function") {
463
- sessionValue = SESSION();
464
- } else {
465
- sessionValue = seedHex(String(SESSION), 8);
466
- }
467
- result = result.replace("{SESSION}", sessionValue);
468
- for (const [key, value] of Object.entries(rest)) {
469
- const v = typeof value === "function" ? value() : String(value);
470
- result = result.replace(`{${key}}`, v);
471
- }
472
- }
473
- return result;
474
- }