@socketsecurity/lib 5.11.2 → 5.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/globs.js CHANGED
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  /* Socket Lib - Built with esbuild */
3
- var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
5
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
7
  var __export = (target, all) => {
10
8
  for (var name in all)
@@ -18,14 +16,6 @@ var __copyProps = (to, from, except, desc) => {
18
16
  }
19
17
  return to;
20
18
  };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
20
  var globs_exports = {};
31
21
  __export(globs_exports, {
@@ -36,10 +26,24 @@ __export(globs_exports, {
36
26
  globSync: () => globSync
37
27
  });
38
28
  module.exports = __toCommonJS(globs_exports);
39
- var fastGlob = __toESM(require("./external/fast-glob.js"));
40
- var import_picomatch = __toESM(require("./external/picomatch.js"));
41
29
  var import_objects = require("./objects");
42
30
  var import_globs = require("./paths/globs");
31
+ let _fastGlob;
32
+ // @__NO_SIDE_EFFECTS__
33
+ function getFastGlob() {
34
+ if (_fastGlob === void 0) {
35
+ _fastGlob = require("./external/fast-glob.js");
36
+ }
37
+ return _fastGlob;
38
+ }
39
+ let _picomatch;
40
+ // @__NO_SIDE_EFFECTS__
41
+ function getPicomatch() {
42
+ if (_picomatch === void 0) {
43
+ _picomatch = require("./external/picomatch.js");
44
+ }
45
+ return _picomatch;
46
+ }
43
47
  const defaultIgnore = (0, import_objects.objectFreeze)([
44
48
  // Most of these ignored files can be included specifically if included in the
45
49
  // files globs. Exceptions to this are:
@@ -95,6 +99,7 @@ function globStreamLicenses(dirname, options) {
95
99
  if (ignoreOriginals) {
96
100
  ignore.push(import_globs.LICENSE_ORIGINAL_GLOB_RECURSIVE);
97
101
  }
102
+ const fastGlob = /* @__PURE__ */ getFastGlob();
98
103
  return fastGlob.globStream(
99
104
  [recursive ? import_globs.LICENSE_GLOB_RECURSIVE : import_globs.LICENSE_GLOB],
100
105
  {
@@ -142,7 +147,8 @@ function getGlobMatcher(glob2, options) {
142
147
  ...options,
143
148
  ...negativePatterns.length > 0 ? { ignore: negativePatterns } : {}
144
149
  };
145
- matcher = (0, import_picomatch.default)(
150
+ const picomatch = /* @__PURE__ */ getPicomatch();
151
+ matcher = picomatch(
146
152
  positivePatterns.length > 0 ? positivePatterns : patterns,
147
153
  matchOptions
148
154
  );
@@ -152,10 +158,12 @@ function getGlobMatcher(glob2, options) {
152
158
  }
153
159
  // @__NO_SIDE_EFFECTS__
154
160
  function glob(patterns, options) {
161
+ const fastGlob = /* @__PURE__ */ getFastGlob();
155
162
  return fastGlob.glob(patterns, options);
156
163
  }
157
164
  // @__NO_SIDE_EFFECTS__
158
165
  function globSync(patterns, options) {
166
+ const fastGlob = /* @__PURE__ */ getFastGlob();
159
167
  return fastGlob.globSync(patterns, options);
160
168
  }
161
169
  // Annotate the CommonJS export names for ESM import in node:
@@ -147,6 +147,15 @@ async function httpDownloadAttempt(url, destPath, options) {
147
147
  return;
148
148
  }
149
149
  const redirectUrl = res.headers.location.startsWith("http") ? res.headers.location : new URL(res.headers.location, url).toString();
150
+ const redirectParsed = new URL(redirectUrl);
151
+ if (isHttps && redirectParsed.protocol !== "https:") {
152
+ reject(
153
+ new Error(
154
+ `Redirect from HTTPS to HTTP is not allowed: ${redirectUrl}`
155
+ )
156
+ );
157
+ return;
158
+ }
150
159
  resolve(
151
160
  httpDownloadAttempt(redirectUrl, destPath, {
152
161
  ca,
@@ -270,6 +279,15 @@ async function httpRequestAttempt(url, options) {
270
279
  return;
271
280
  }
272
281
  const redirectUrl = res.headers.location.startsWith("http") ? res.headers.location : new URL(res.headers.location, url).toString();
282
+ const redirectParsed = new URL(redirectUrl);
283
+ if (isHttps && redirectParsed.protocol !== "https:") {
284
+ reject(
285
+ new Error(
286
+ `Redirect from HTTPS to HTTP is not allowed: ${redirectUrl}`
287
+ )
288
+ );
289
+ return;
290
+ }
273
291
  resolve(
274
292
  httpRequestAttempt(redirectUrl, {
275
293
  body,
@@ -311,6 +329,9 @@ async function httpRequestAttempt(url, options) {
311
329
  };
312
330
  resolve(response);
313
331
  });
332
+ res.on("error", (error) => {
333
+ reject(error);
334
+ });
314
335
  }
315
336
  );
316
337
  request.on("error", (error) => {
@@ -369,8 +390,10 @@ async function httpDownload(url, destPath, options) {
369
390
  }
370
391
  };
371
392
  }
393
+ const crypto = /* @__PURE__ */ getCrypto();
372
394
  const fs = /* @__PURE__ */ getFs();
373
- const tempPath = `${destPath}.download`;
395
+ const tempSuffix = crypto.randomBytes(6).toString("hex");
396
+ const tempPath = `${destPath}.${tempSuffix}.download`;
374
397
  if (fs.existsSync(tempPath)) {
375
398
  await (0, import_fs.safeDelete)(tempPath);
376
399
  }
@@ -386,14 +409,17 @@ async function httpDownload(url, destPath, options) {
386
409
  timeout
387
410
  });
388
411
  if (sha256) {
389
- const crypto = /* @__PURE__ */ getCrypto();
390
412
  const fileContent = await fs.promises.readFile(tempPath);
391
413
  const computedHash = crypto.createHash("sha256").update(fileContent).digest("hex");
392
- if (computedHash !== sha256.toLowerCase()) {
414
+ const expectedHash = sha256.toLowerCase();
415
+ if (computedHash.length !== expectedHash.length || !crypto.timingSafeEqual(
416
+ Buffer.from(computedHash),
417
+ Buffer.from(expectedHash)
418
+ )) {
393
419
  await (0, import_fs.safeDelete)(tempPath);
394
420
  throw new Error(
395
421
  `Checksum verification failed for ${url}
396
- Expected: ${sha256.toLowerCase()}
422
+ Expected: ${expectedHash}
397
423
  Computed: ${computedHash}`
398
424
  );
399
425
  }
package/dist/ipc.js CHANGED
@@ -116,7 +116,7 @@ async function ensureIpcDirectory(filePath) {
116
116
  const fs = /* @__PURE__ */ getFs();
117
117
  const path = /* @__PURE__ */ getPath();
118
118
  const dir = path.dirname(filePath);
119
- await fs.promises.mkdir(dir, { recursive: true });
119
+ await fs.promises.mkdir(dir, { recursive: true, mode: 448 });
120
120
  }
121
121
  async function writeIpcStub(appName, data) {
122
122
  const stubPath = getIpcStubPath(appName);
@@ -128,11 +128,10 @@ async function writeIpcStub(appName, data) {
128
128
  };
129
129
  const validated = IpcStubSchema.parse(ipcData);
130
130
  const fs = /* @__PURE__ */ getFs();
131
- await fs.promises.writeFile(
132
- stubPath,
133
- JSON.stringify(validated, null, 2),
134
- "utf8"
135
- );
131
+ await fs.promises.writeFile(stubPath, JSON.stringify(validated, null, 2), {
132
+ encoding: "utf8",
133
+ mode: 384
134
+ });
136
135
  return stubPath;
137
136
  }
138
137
  async function readIpcStub(stubPath) {
@@ -179,6 +178,7 @@ async function cleanupIpcStubs(appName) {
179
178
  const contentAge = now - validated.timestamp;
180
179
  isStale = isStale || contentAge > maxAgeMs;
181
180
  } catch {
181
+ isStale = true;
182
182
  }
183
183
  if (isStale) {
184
184
  (0, import_fs.safeDeleteSync)(filePath, { force: true });
@@ -239,6 +239,7 @@ function waitForIpc(messageType, options = {}) {
239
239
  cleanup = onIpc(handleMessage);
240
240
  if (timeout > 0) {
241
241
  timeoutId = setTimeout(handleTimeout, timeout);
242
+ timeoutId.unref();
242
243
  }
243
244
  });
244
245
  }
@@ -29,6 +29,7 @@ __export(memoization_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(memoization_exports);
31
31
  var import_debug = require("./debug");
32
+ const cacheRegistry = [];
32
33
  function memoize(fn, options = {}) {
33
34
  const {
34
35
  keyGen = (...args) => JSON.stringify(args),
@@ -41,6 +42,10 @@ function memoize(fn, options = {}) {
41
42
  }
42
43
  const cache = /* @__PURE__ */ new Map();
43
44
  const accessOrder = [];
45
+ cacheRegistry.push(() => {
46
+ cache.clear();
47
+ accessOrder.length = 0;
48
+ });
44
49
  function evictLRU() {
45
50
  if (cache.size >= maxSize && accessOrder.length > 0) {
46
51
  const oldest = accessOrder.shift();
@@ -62,15 +67,22 @@ function memoize(fn, options = {}) {
62
67
  return function memoized(...args) {
63
68
  const key = keyGen(...args);
64
69
  const cached = cache.get(key);
65
- if (cached && !isExpired(cached)) {
66
- cached.hits++;
70
+ if (cached) {
71
+ if (!isExpired(cached)) {
72
+ cached.hits++;
73
+ const index2 = accessOrder.indexOf(key);
74
+ if (index2 !== -1) {
75
+ accessOrder.splice(index2, 1);
76
+ }
77
+ accessOrder.push(key);
78
+ (0, import_debug.debugLog)(`[memoize:${name}] hit`, { key, hits: cached.hits });
79
+ return cached.value;
80
+ }
81
+ cache.delete(key);
67
82
  const index = accessOrder.indexOf(key);
68
83
  if (index !== -1) {
69
84
  accessOrder.splice(index, 1);
70
85
  }
71
- accessOrder.push(key);
72
- (0, import_debug.debugLog)(`[memoize:${name}] hit`, { key, hits: cached.hits });
73
- return cached.value;
74
86
  }
75
87
  (0, import_debug.debugLog)(`[memoize:${name}] miss`, { key });
76
88
  const value = fn(...args);
@@ -94,6 +106,10 @@ function memoizeAsync(fn, options = {}) {
94
106
  } = options;
95
107
  const cache = /* @__PURE__ */ new Map();
96
108
  const accessOrder = [];
109
+ cacheRegistry.push(() => {
110
+ cache.clear();
111
+ accessOrder.length = 0;
112
+ });
97
113
  function evictLRU() {
98
114
  if (cache.size >= maxSize && accessOrder.length > 0) {
99
115
  const oldest = accessOrder.shift();
@@ -112,22 +128,36 @@ function memoizeAsync(fn, options = {}) {
112
128
  }
113
129
  return Date.now() - entry.timestamp > ttl;
114
130
  }
131
+ const refreshing = /* @__PURE__ */ new Set();
115
132
  return async function memoized(...args) {
116
133
  const key = keyGen(...args);
117
134
  const cached = cache.get(key);
118
- if (cached && !isExpired(cached)) {
119
- cached.hits++;
135
+ if (cached) {
136
+ if (!isExpired(cached)) {
137
+ cached.hits++;
138
+ const index2 = accessOrder.indexOf(key);
139
+ if (index2 !== -1) {
140
+ accessOrder.splice(index2, 1);
141
+ }
142
+ accessOrder.push(key);
143
+ (0, import_debug.debugLog)(`[memoizeAsync:${name}] hit`, { key, hits: cached.hits });
144
+ return await cached.value;
145
+ }
146
+ if (refreshing.has(key)) {
147
+ (0, import_debug.debugLog)(`[memoizeAsync:${name}] stale-dedup`, { key });
148
+ return await cached.value;
149
+ }
150
+ cache.delete(key);
120
151
  const index = accessOrder.indexOf(key);
121
152
  if (index !== -1) {
122
153
  accessOrder.splice(index, 1);
123
154
  }
124
- accessOrder.push(key);
125
- (0, import_debug.debugLog)(`[memoizeAsync:${name}] hit`, { key, hits: cached.hits });
126
- return await cached.value;
127
155
  }
128
156
  (0, import_debug.debugLog)(`[memoizeAsync:${name}] miss`, { key });
157
+ refreshing.add(key);
129
158
  const promise = fn(...args).then(
130
159
  (result) => {
160
+ refreshing.delete(key);
131
161
  const entry = cache.get(key);
132
162
  if (entry) {
133
163
  entry.value = Promise.resolve(result);
@@ -135,6 +165,7 @@ function memoizeAsync(fn, options = {}) {
135
165
  return result;
136
166
  },
137
167
  (error) => {
168
+ refreshing.delete(key);
138
169
  cache.delete(key);
139
170
  const index = accessOrder.indexOf(key);
140
171
  if (index !== -1) {
@@ -167,14 +198,16 @@ function Memoize(options = {}) {
167
198
  }
168
199
  function clearAllMemoizationCaches() {
169
200
  (0, import_debug.debugLog)("[memoize:all] clear", { action: "clear-all-caches" });
201
+ for (const clear of cacheRegistry) {
202
+ clear();
203
+ }
170
204
  }
171
205
  function memoizeWeak(fn) {
172
206
  const cache = /* @__PURE__ */ new WeakMap();
173
207
  return function memoized(key) {
174
- const cached = cache.get(key);
175
- if (cached !== void 0) {
208
+ if (cache.has(key)) {
176
209
  (0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] hit`);
177
- return cached;
210
+ return cache.get(key);
178
211
  }
179
212
  (0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] miss`);
180
213
  const result = fn(key);
@@ -69,7 +69,15 @@ async function resolveRealPath(pathStr) {
69
69
  }
70
70
  async function mergePackageJson(pkgJsonPath, originalPkgJson) {
71
71
  const fs = /* @__PURE__ */ getFs();
72
- const pkgJson = JSON.parse(await fs.promises.readFile(pkgJsonPath, "utf8"));
72
+ let pkgJson;
73
+ try {
74
+ pkgJson = JSON.parse(await fs.promises.readFile(pkgJsonPath, "utf8"));
75
+ } catch (error) {
76
+ throw new Error(
77
+ `Failed to parse ${pkgJsonPath}: ${error instanceof Error ? error.message : String(error)}`,
78
+ { cause: error }
79
+ );
80
+ }
73
81
  const mergedPkgJson = originalPkgJson ? { ...originalPkgJson, ...pkgJson } : pkgJson;
74
82
  return mergedPkgJson;
75
83
  }
@@ -179,7 +179,14 @@ class ProcessLockManager {
179
179
  if (existsSync(lockPath)) {
180
180
  throw new Error(`Lock already exists: ${lockPath}`);
181
181
  }
182
- mkdirSync(lockPath, { recursive: true });
182
+ const lastSlash = Math.max(
183
+ lockPath.lastIndexOf("/"),
184
+ lockPath.lastIndexOf("\\")
185
+ );
186
+ if (lastSlash > 0) {
187
+ mkdirSync(lockPath.slice(0, lastSlash), { recursive: true });
188
+ }
189
+ mkdirSync(lockPath);
183
190
  this.activeLocks.add(lockPath);
184
191
  this.startTouchTimer(lockPath, touchIntervalMs);
185
192
  return () => this.release(lockPath);
@@ -204,7 +211,10 @@ class ProcessLockManager {
204
211
  );
205
212
  }
206
213
  if (code === "ENOTDIR") {
207
- const lastSlashIndex = lockPath.lastIndexOf("/");
214
+ const lastSlashIndex = Math.max(
215
+ lockPath.lastIndexOf("/"),
216
+ lockPath.lastIndexOf("\\")
217
+ );
208
218
  const parentDir = lastSlashIndex === -1 ? "." : lockPath.slice(0, lastSlashIndex);
209
219
  throw new Error(
210
220
  `Cannot create lock directory: ${lockPath}
@@ -218,7 +228,10 @@ To resolve:
218
228
  );
219
229
  }
220
230
  if (code === "ENOENT") {
221
- const lastSlashIndex = lockPath.lastIndexOf("/");
231
+ const lastSlashIndex = Math.max(
232
+ lockPath.lastIndexOf("/"),
233
+ lockPath.lastIndexOf("\\")
234
+ );
222
235
  const parentDir = lastSlashIndex === -1 ? "." : lockPath.slice(0, lastSlashIndex);
223
236
  throw new Error(
224
237
  `Cannot create lock directory: ${lockPath}
@@ -1,6 +1,7 @@
1
1
  export declare class PromiseQueue {
2
2
  private queue;
3
3
  private running;
4
+ private idleResolvers;
4
5
  private readonly maxConcurrency;
5
6
  private readonly maxQueueLength;
6
7
  /**
@@ -16,6 +17,7 @@ export declare class PromiseQueue {
16
17
  */
17
18
  add<T>(fn: () => Promise<T>): Promise<T>;
18
19
  private runNext;
20
+ private notifyIdleIfNeeded;
19
21
  /**
20
22
  * Wait for all queued and running tasks to complete
21
23
  */
@@ -25,6 +25,7 @@ module.exports = __toCommonJS(promise_queue_exports);
25
25
  class PromiseQueue {
26
26
  queue = [];
27
27
  running = 0;
28
+ idleResolvers = [];
28
29
  maxConcurrency;
29
30
  maxQueueLength;
30
31
  /**
@@ -47,7 +48,7 @@ class PromiseQueue {
47
48
  async add(fn) {
48
49
  return await new Promise((resolve, reject) => {
49
50
  const task = { fn, resolve, reject };
50
- if (this.maxQueueLength && this.queue.length >= this.maxQueueLength) {
51
+ if (this.maxQueueLength !== void 0 && this.queue.length >= this.maxQueueLength) {
51
52
  const droppedTask = this.queue.shift();
52
53
  if (droppedTask) {
53
54
  droppedTask.reject(new Error("Task dropped: queue length exceeded"));
@@ -59,6 +60,7 @@ class PromiseQueue {
59
60
  }
60
61
  runNext() {
61
62
  if (this.running >= this.maxConcurrency || this.queue.length === 0) {
63
+ this.notifyIdleIfNeeded();
62
64
  return;
63
65
  }
64
66
  const task = this.queue.shift();
@@ -71,19 +73,23 @@ class PromiseQueue {
71
73
  this.runNext();
72
74
  });
73
75
  }
76
+ notifyIdleIfNeeded() {
77
+ if (this.running === 0 && this.queue.length === 0) {
78
+ for (const resolve of this.idleResolvers) {
79
+ resolve();
80
+ }
81
+ this.idleResolvers = [];
82
+ }
83
+ }
74
84
  /**
75
85
  * Wait for all queued and running tasks to complete
76
86
  */
77
87
  async onIdle() {
88
+ if (this.running === 0 && this.queue.length === 0) {
89
+ return;
90
+ }
78
91
  return await new Promise((resolve) => {
79
- const check = () => {
80
- if (this.running === 0 && this.queue.length === 0) {
81
- resolve();
82
- } else {
83
- setImmediate(check);
84
- }
85
- };
86
- check();
92
+ this.idleResolvers.push(resolve);
87
93
  });
88
94
  }
89
95
  /**
@@ -102,7 +108,12 @@ class PromiseQueue {
102
108
  * Clear all pending tasks from the queue (does not affect running tasks)
103
109
  */
104
110
  clear() {
111
+ const pending = this.queue;
105
112
  this.queue = [];
113
+ for (const task of pending) {
114
+ task.reject(new Error("Task cancelled: queue cleared"));
115
+ }
116
+ this.notifyIdleIfNeeded();
106
117
  }
107
118
  }
108
119
  // Annotate the CommonJS export names for ESM import in node:
package/dist/promises.js CHANGED
@@ -203,9 +203,7 @@ async function pRetry(callbackFn, options) {
203
203
  try {
204
204
  return await callbackFn(...args || [], { signal });
205
205
  } catch (e) {
206
- if (error === import_core.UNDEFINED_TOKEN) {
207
- error = e;
208
- }
206
+ error = e;
209
207
  if (attempts < 0) {
210
208
  break;
211
209
  }
@@ -294,7 +294,11 @@ async function getReleaseAssetUrl(tag, assetPattern, repoConfig, options = {}) {
294
294
  { cause }
295
295
  );
296
296
  }
297
- const asset = release.assets.find((a) => isMatch(a.name));
297
+ const assets = release.assets;
298
+ if (!Array.isArray(assets)) {
299
+ throw new Error(`Release ${tag} has no assets`);
300
+ }
301
+ const asset = assets.find((a) => isMatch(a.name));
298
302
  if (!asset) {
299
303
  const patternDesc = typeof assetPattern === "string" ? assetPattern : "matching pattern";
300
304
  throw new Error(`Asset ${patternDesc} not found in release ${tag}`);
package/dist/sorts.js CHANGED
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  /* Socket Lib - Built with esbuild */
3
- var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
5
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
7
  var __export = (target, all) => {
10
8
  for (var name in all)
@@ -18,14 +16,6 @@ var __copyProps = (to, from, except, desc) => {
18
16
  }
19
17
  return to;
20
18
  };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
20
  var sorts_exports = {};
31
21
  __export(sorts_exports, {
@@ -36,10 +26,23 @@ __export(sorts_exports, {
36
26
  naturalSorter: () => naturalSorter
37
27
  });
38
28
  module.exports = __toCommonJS(sorts_exports);
39
- var fastSort = __toESM(require("./external/fast-sort.js"));
40
- var semver = __toESM(require("./external/semver.js"));
29
+ let _semver;
30
+ function getSemver() {
31
+ if (_semver === void 0) {
32
+ _semver = require("./external/semver.js");
33
+ }
34
+ return _semver;
35
+ }
36
+ let _fastSort;
37
+ function getFastSort() {
38
+ if (_fastSort === void 0) {
39
+ _fastSort = require("./external/fast-sort.js");
40
+ }
41
+ return _fastSort;
42
+ }
41
43
  // @__NO_SIDE_EFFECTS__
42
44
  function compareSemver(a, b) {
45
+ const semver = getSemver();
43
46
  const validA = semver.valid(a);
44
47
  const validB = semver.valid(b);
45
48
  if (!validA && !validB) {
@@ -90,6 +93,7 @@ let _naturalSorter;
90
93
  // @__NO_SIDE_EFFECTS__
91
94
  function naturalSorter(arrayToSort) {
92
95
  if (_naturalSorter === void 0) {
96
+ const fastSort = getFastSort();
93
97
  _naturalSorter = fastSort.createNewSortInstance({
94
98
  comparer: naturalCompare
95
99
  });
package/dist/spawn.js CHANGED
@@ -39,13 +39,20 @@ module.exports = __toCommonJS(spawn_exports);
39
39
  var import_node_process = __toESM(require("node:process"));
40
40
  var import_process = require("./constants/process");
41
41
  var import_errors = require("./errors");
42
- var import_promise_spawn = __toESM(require("./external/@npmcli/promise-spawn"));
43
42
  var import_arrays = require("./arrays");
44
43
  var import_bin = require("./bin");
45
44
  var import_normalize = require("./paths/normalize");
46
45
  var import_objects = require("./objects");
47
46
  var import_spinner = require("./spinner");
48
47
  var import_strings = require("./strings");
48
+ let _npmCliPromiseSpawn;
49
+ // @__NO_SIDE_EFFECTS__
50
+ function getNpmCliPromiseSpawn() {
51
+ if (_npmCliPromiseSpawn === void 0) {
52
+ _npmCliPromiseSpawn = require("./external/@npmcli/promise-spawn");
53
+ }
54
+ return _npmCliPromiseSpawn;
55
+ }
49
56
  let _path;
50
57
  // @__NO_SIDE_EFFECTS__
51
58
  function getPath() {
@@ -235,7 +242,8 @@ function spawn(cmd, args, options, extra) {
235
242
  uid: spawnOptions.uid,
236
243
  gid: spawnOptions.gid
237
244
  };
238
- const spawnPromise = (0, import_promise_spawn.default)(
245
+ const npmCliPromiseSpawn = /* @__PURE__ */ getNpmCliPromiseSpawn();
246
+ const spawnPromise = npmCliPromiseSpawn(
239
247
  actualCmd,
240
248
  args ? [...args] : [],
241
249
  promiseSpawnOpts,
@@ -196,7 +196,7 @@ class ProgressBar {
196
196
  }
197
197
  }
198
198
  function createProgressIndicator(current, total, label) {
199
- const percent = Math.floor(current / total * 100);
199
+ const percent = total === 0 ? 0 : Math.floor(current / total * 100);
200
200
  const progress = `${current}/${total}`;
201
201
  let output = "";
202
202
  if (label) {
package/dist/strings.js CHANGED
@@ -37,7 +37,14 @@ __export(strings_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(strings_exports);
39
39
  var import_ansi = require("./ansi");
40
- var import_get_east_asian_width = require("./external/get-east-asian-width");
40
+ let _eastAsianWidth;
41
+ // @__NO_SIDE_EFFECTS__
42
+ function getEastAsianWidth() {
43
+ if (_eastAsianWidth === void 0) {
44
+ _eastAsianWidth = require("./external/get-east-asian-width").eastAsianWidth;
45
+ }
46
+ return _eastAsianWidth;
47
+ }
41
48
  const fromCharCode = String.fromCharCode;
42
49
  // @__NO_SIDE_EFFECTS__
43
50
  function applyLinePrefix(str, options) {
@@ -164,6 +171,7 @@ function stringWidth(text) {
164
171
  }
165
172
  let width = 0;
166
173
  const eastAsianWidthOptions = { ambiguousAsWide: false };
174
+ const eastAsianWidth = /* @__PURE__ */ getEastAsianWidth();
167
175
  for (const { segment } of segmenter.segment(plainText)) {
168
176
  if (zeroWidthClusterRegex.test(segment)) {
169
177
  continue;
@@ -177,14 +185,14 @@ function stringWidth(text) {
177
185
  if (codePoint === void 0) {
178
186
  continue;
179
187
  }
180
- width += (0, import_get_east_asian_width.eastAsianWidth)(codePoint, eastAsianWidthOptions);
188
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
181
189
  if (segment.length > 1) {
182
190
  for (const char of segment.slice(1)) {
183
191
  const charCode = char.charCodeAt(0);
184
192
  if (charCode >= 65280 && charCode <= 65519) {
185
193
  const trailingCodePoint = char.codePointAt(0);
186
194
  if (trailingCodePoint !== void 0) {
187
- width += (0, import_get_east_asian_width.eastAsianWidth)(trailingCodePoint, eastAsianWidthOptions);
195
+ width += eastAsianWidth(trailingCodePoint, eastAsianWidthOptions);
188
196
  }
189
197
  }
190
198
  }
@@ -27,7 +27,15 @@ __export(json_parser_exports, {
27
27
  tryJsonParse: () => tryJsonParse
28
28
  });
29
29
  module.exports = __toCommonJS(json_parser_exports);
30
- const { hasOwn: ObjectHasOwn } = Object;
30
+ const DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
31
+ function prototypePollutionReviver(key, value) {
32
+ if (DANGEROUS_KEYS.has(key)) {
33
+ throw new Error(
34
+ "JSON contains potentially malicious prototype pollution keys"
35
+ );
36
+ }
37
+ return value;
38
+ }
31
39
  function safeJsonParse(jsonString, schema, options = {}) {
32
40
  const { allowPrototype = false, maxSize = 10 * 1024 * 1024 } = options;
33
41
  const byteLength = Buffer.byteLength(jsonString, "utf8");
@@ -38,20 +46,10 @@ function safeJsonParse(jsonString, schema, options = {}) {
38
46
  }
39
47
  let parsed;
40
48
  try {
41
- parsed = JSON.parse(jsonString);
49
+ parsed = allowPrototype ? JSON.parse(jsonString) : JSON.parse(jsonString, prototypePollutionReviver);
42
50
  } catch (error) {
43
51
  throw new Error(`Failed to parse JSON: ${error}`);
44
52
  }
45
- if (!allowPrototype && typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
46
- const dangerous = ["__proto__", "constructor", "prototype"];
47
- for (const key of dangerous) {
48
- if (ObjectHasOwn(parsed, key)) {
49
- throw new Error(
50
- "JSON contains potentially malicious prototype pollution keys"
51
- );
52
- }
53
- }
54
- }
55
53
  if (schema) {
56
54
  const result = schema.safeParse(parsed);
57
55
  if (!result.success) {