From abdf4aec1d2839292d2c0a732237997623891832 Mon Sep 17 00:00:00 2001
From: Anthony Fu <github@antfu.me>
Date: Thu, 31 Oct 2024 04:43:22 +0900
Subject: [PATCH] feat: add concurrency limit

---
 package.json       |  1 +
 pnpm-lock.yaml     | 21 +++++++++++++++++++--
 src/io/resolves.ts | 20 +++++++++++++-------
 src/types.ts       |  6 ++++++
 4 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 9d40f94..0167af4 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
     "@antfu/ni": "^0.23.0",
     "js-yaml": "^4.1.0",
     "ofetch": "^1.4.0",
+    "p-limit": "^6.1.0",
     "package-manager-detector": "^0.2.0",
     "tinyexec": "^0.3.0",
     "unconfig": "^0.6.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4d950ef..ccc83d1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,6 +17,9 @@ importers:
       ofetch:
         specifier: ^1.4.0
         version: 1.4.0
+      p-limit:
+        specifier: ^6.1.0
+        version: 6.1.0
       package-manager-detector:
         specifier: ^0.2.0
         version: 0.2.0
@@ -1520,7 +1523,7 @@ packages:
     resolution: {integrity: sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg==}
     engines: {node: '>=18'}
     peerDependencies:
-      eslint: ^9.11.1
+      eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
 
   eslint-plugin-jsonc@2.16.0:
     resolution: {integrity: sha512-Af/ZL5mgfb8FFNleH6KlO4/VdmDuTqmM+SPnWcdoWywTetv7kq+vQe99UyQb9XO3b0OWLVuTH7H0d/PXYCMdSg==}
@@ -1543,7 +1546,7 @@ packages:
     engines: {node: ^18.0.0 || >=20.0.0}
     peerDependencies:
       astro-eslint-parser: ^1.0.2
-      eslint: ^9.11.1
+      eslint: '>=8.0.0'
       svelte: '>=3.0.0'
       svelte-eslint-parser: ^0.41.1
       vue-eslint-parser: '>=9.0.0'
@@ -2448,6 +2451,10 @@ packages:
     resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
     engines: {node: '>=10'}
 
+  p-limit@6.1.0:
+    resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==}
+    engines: {node: '>=18'}
+
   p-locate@4.1.0:
     resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
     engines: {node: '>=8'}
@@ -3284,6 +3291,10 @@ packages:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
 
+  yocto-queue@1.1.1:
+    resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==}
+    engines: {node: '>=12.20'}
+
   zwitch@2.0.4:
     resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
 
@@ -5893,6 +5904,10 @@ snapshots:
     dependencies:
       yocto-queue: 0.1.0
 
+  p-limit@6.1.0:
+    dependencies:
+      yocto-queue: 1.1.1
+
   p-locate@4.1.0:
     dependencies:
       p-limit: 2.3.0
@@ -6706,4 +6721,6 @@ snapshots:
 
   yocto-queue@0.1.0: {}
 
+  yocto-queue@1.1.1: {}
+
   zwitch@2.0.4: {}
diff --git a/src/io/resolves.ts b/src/io/resolves.ts
index 724aad0..a69ff23 100644
--- a/src/io/resolves.ts
+++ b/src/io/resolves.ts
@@ -3,6 +3,7 @@ import { existsSync, promises as fs, lstatSync } from 'node:fs'
 import os from 'node:os'
 import { resolve } from 'node:path'
 import _debug from 'debug'
+import pLimit from 'p-limit'
 import semver from 'semver'
 import { diffSorter } from '../filters/diff-sorter'
 import { getPackageMode } from '../utils/config'
@@ -268,14 +269,19 @@ export async function resolveDependencies(
   const total = deps.length
   let counter = 0
 
+  const {
+    concurrency = 10,
+  } = options
+
+  const limit = pLimit(concurrency)
+
   return Promise.all(
-    deps
-      .map(async (raw) => {
-        const dep = await resolveDependency(raw, options, filter)
-        counter += 1
-        progressCallback(raw.name, counter, total)
-        return dep
-      }),
+    deps.map(raw => limit(async () => {
+      const dep = await resolveDependency(raw, options, filter)
+      counter += 1
+      progressCallback(raw.name, counter, total)
+      return dep
+    })),
   )
 }
 
diff --git a/src/types.ts b/src/types.ts
index 1113a0b..3fc797c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -103,6 +103,12 @@ export interface CheckOptions extends CommonOptions {
   install?: boolean
   update?: boolean
   global?: boolean
+  /**
+   * Number of concurrent requests
+   *
+   * @default 10
+   */
+  concurrency?: number
   /**
    * Group dependencies by source, e.g. dependencies, devDependencies, etc.
    *