Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fs from 'node:fs/promises'
import { existsSync } from 'node:fs'
import { resolve as pathResolve } from 'node:path'
import { defineNuxtModule, addPlugin, addServerHandler, hasNuxtModule, createResolver, addComponent, logger, updateTemplates, resolvePath as nuxtResolvePath, addVitePlugin } from '@nuxt/kit'
import { addCustomTab } from '@nuxt/devtools-kit'
import { resolvePath } from 'mlly'
Expand Down Expand Up @@ -87,6 +89,10 @@ export default defineNuxtModule<ModuleOptions>({

await setupCustomCollectionsWatcher(options, nuxt, ctx)

// Detect package manager for install suggestions
const pmInstallCommand = detectInstallCommand(nuxt.options.rootDir)
nuxt.options.runtimeConfig.public.nuxtIconInstallCommand = pmInstallCommand

// Merge options to app.config
const runtimeOptions = Object.fromEntries(
Object.entries(options)
Expand Down Expand Up @@ -224,3 +230,16 @@ async function setupCustomCollectionsWatcher(options: ModuleOptions, nuxt: Nuxt,
}
})
}

function detectInstallCommand(rootDir: string): string {
if (existsSync(pathResolve(rootDir, 'pnpm-lock.yaml'))) {
return 'pnpm add -D'
}
if (existsSync(pathResolve(rootDir, 'yarn.lock'))) {
return 'yarn add -D'
}
if (existsSync(pathResolve(rootDir, 'bun.lockb')) || existsSync(pathResolve(rootDir, 'bun.lock'))) {
return 'bun add -D'
}
return 'npm i -D'
}
Comment on lines +241 to +252
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Package manager detection misses common monorepo layouts.

This only checks one directory. If the lockfile lives in a parent workspace directory, the warning still falls back to npm i -D, so detection is incorrect for those projects.

Suggested fix
 function detectInstallCommand(rootDir: string): string {
-  if (existsSync(pathResolve(rootDir, 'pnpm-lock.yaml'))) {
-    return 'pnpm add -D'
-  }
-  if (existsSync(pathResolve(rootDir, 'yarn.lock'))) {
-    return 'yarn add -D'
-  }
-  if (existsSync(pathResolve(rootDir, 'bun.lockb')) || existsSync(pathResolve(rootDir, 'bun.lock'))) {
-    return 'bun add -D'
-  }
+  const lockfileCommandPairs: Array<[string, string]> = [
+    ['pnpm-lock.yaml', 'pnpm add -D'],
+    ['yarn.lock', 'yarn add -D'],
+    ['bun.lockb', 'bun add -D'],
+    ['bun.lock', 'bun add -D'],
+  ]
+
+  let currentDir = rootDir
+  while (true) {
+    for (const [lockfile, command] of lockfileCommandPairs) {
+      if (existsSync(pathResolve(currentDir, lockfile))) {
+        return command
+      }
+    }
+
+    const parentDir = pathResolve(currentDir, '..')
+    if (parentDir === currentDir) {
+      break
+    }
+    currentDir = parentDir
+  }
+
   return 'npm i -D'
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function detectInstallCommand(rootDir: string): string {
if (existsSync(pathResolve(rootDir, 'pnpm-lock.yaml'))) {
return 'pnpm add -D'
}
if (existsSync(pathResolve(rootDir, 'yarn.lock'))) {
return 'yarn add -D'
}
if (existsSync(pathResolve(rootDir, 'bun.lockb')) || existsSync(pathResolve(rootDir, 'bun.lock'))) {
return 'bun add -D'
}
return 'npm i -D'
}
function detectInstallCommand(rootDir: string): string {
const lockfileCommandPairs: Array<[string, string]> = [
['pnpm-lock.yaml', 'pnpm add -D'],
['yarn.lock', 'yarn add -D'],
['bun.lockb', 'bun add -D'],
['bun.lock', 'bun add -D'],
]
let currentDir = rootDir
while (true) {
for (const [lockfile, command] of lockfileCommandPairs) {
if (existsSync(pathResolve(currentDir, lockfile))) {
return command
}
}
const parentDir = pathResolve(currentDir, '..')
if (parentDir === currentDir) {
break
}
currentDir = parentDir
}
return 'npm i -D'
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/module.ts` around lines 234 - 245, The detectInstallCommand function only
checks lockfiles in the provided rootDir and misses parent workspace/monorepo
layouts; update detectInstallCommand to walk up parent directories from rootDir
to filesystem root (or stop at a workspace boundary) and check for known
indicators in each directory—pnpm-lock.yaml or pnpm-workspace.yaml => 'pnpm add
-D', yarn.lock or yarn workspaces indicators or package.json with "workspaces"
=> 'yarn add -D', bun.lockb or bun.lock => 'bun add -D', and fallback to
package.json's "packageManager" field if present before finally returning 'npm i
-D'; reference detectInstallCommand and the helper pathResolve/existsSync
utilities when adding the upward directory traversal and checks.

5 changes: 3 additions & 2 deletions src/runtime/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createError, getQuery, type H3Event } from 'h3'
import { consola } from 'consola'
import type { NuxtIconRuntimeOptions } from '../../schema-types'
// @ts-expect-error tsconfig.server has the types
import { useAppConfig, getRequestURL, defineCachedEventHandler } from '#imports'
import { useAppConfig, useRuntimeConfig, getRequestURL, defineCachedEventHandler } from '#imports'
import { collections } from '#nuxt-icon-server-bundle'

const warnOnceSet = /* @__PURE__ */ new Set<string>()
Expand Down Expand Up @@ -39,9 +39,10 @@ export default defineCachedEventHandler(async (event: H3Event) => {
else if (import.meta.dev) {
// Warn only once per collection, and only with the default endpoint
if (collectionName && !warnOnceSet.has(collectionName) && apiEndPoint === DEFAULT_ENDPOINT) {
const installCmd = useRuntimeConfig().public?.nuxtIconInstallCommand || 'npm i -D'
consola.warn([
`[Icon] Collection \`${collectionName}\` is not found locally`,
`We suggest to install it via \`npm i -D @iconify-json/${collectionName}\` to provide the best end-user experience.`,
`We suggest to install it via \`${installCmd} @iconify-json/${collectionName}\` to provide the best end-user experience.`,
].join('\n'))
warnOnceSet.add(collectionName)
}
Expand Down
Loading