Add CLI command typo detection (#34836)#10
Add CLI command typo detection (#34836)#10MitchLewis930 wants to merge 1 commit intopr_040_beforefrom
Conversation
* Add CLI command typo detection * Apply suggestions from code review Co-authored-by: Steven <steven@ceriously.com> * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: Steven <steven@ceriously.com>
📝 WalkthroughWalkthroughIntroduces a typo detection feature for the Next.js CLI that suggests corrections when invalid commands are provided. A new utility implements Levenshtein distance algorithm; the project directory resolver integrates detection into its error handling path. The commands export is made public to support this feature. Changes
Sequence DiagramsequenceDiagram
actor User
participant CLI as Next.js CLI
participant Resolver as getProjectDir()
participant Detector as detectTypo()
participant Output as Error Output
User->>CLI: Enter invalid command (typo)
CLI->>Resolver: Resolve project directory
Resolver->>Resolver: Check if directory exists
alt Directory not found (ENOENT)
Resolver->>Detector: detectTypo(invalid_command, available_commands)
Detector->>Detector: Calculate Levenshtein distances
Detector->>Detector: Filter matches by threshold
Detector->>Resolver: Return closest match or null
alt Match found
Resolver->>Output: Log suggestion message
Output->>User: "Did you mean 'next <correct>'?"
else No match
Resolver->>Output: Log original error
Output->>User: Original error message
end
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/next/lib/get-project-dir.ts`:
- Around line 3-5: getProjectDir imports ../bin/next which triggers heavy side
effects (dependency checks, CLI parsing/execution, process.exit, env and signal
handlers); extract the simple commands list into a new side-effect-free module
(e.g., packages/next/lib/commands.ts) that exports the command names
array/object and import that module from both bin/next.ts and get-project-dir.ts
instead of importing ../bin/next; in practice remove the import of ../bin/next
from get-project-dir.ts, create and export the same `commands` symbol from the
new commands.ts, and update bin/next.ts to import `commands` from commands.ts so
behavior is preserved without executing the CLI side effects.
🧹 Nitpick comments (1)
packages/next/lib/detect-typo.ts (1)
2-28: Usethresholdto short‑circuit the distance computation.
thresholdis currently unused inminDistance, so the full O(m·n) matrix is always computed even when the result will exceed the threshold. Consider an early exit to keep this cheap (and make the parameter meaningful).♻️ Proposed refactor (early exit)
function minDistance(a: string, b: string, threshold: number): number { const m = a.length const n = b.length + if (Math.abs(m - n) > threshold) { + return threshold + 1 + } if (m < n) { return minDistance(b, a, threshold) } @@ for (let j = 0; j < n; j++) { const s2 = b[j] const insertions = previousRow[j + 1] + 1 const deletions = currentRow[j] + 1 const substitutions = previousRow[j] + Number(s1 !== s2) currentRow.push(Math.min(insertions, deletions, substitutions)) } + if (Math.min(...currentRow) > threshold) { + return threshold + 1 + } previousRow = currentRow } return previousRow[previousRow.length - 1] }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/next/bin/next.tspackages/next/lib/detect-typo.tspackages/next/lib/get-project-dir.tstest/integration/cli/test/index.test.js
🧰 Additional context used
🧬 Code graph analysis (2)
test/integration/cli/test/index.test.js (1)
test/lib/next-test-utils.js (2)
check(452-479)runNextCommand(129-219)
packages/next/lib/get-project-dir.ts (3)
test/integration/cli/test/index.test.js (1)
dir(15-15)packages/next/lib/detect-typo.ts (1)
detectTypo(31-44)packages/next/bin/next.ts (1)
commands(18-27)
🔇 Additional comments (4)
packages/next/lib/detect-typo.ts (1)
31-43: Nice, concise selection logic.
The filtering and closest-match selection are clear and easy to reason about.packages/next/bin/next.ts (1)
17-18: Exportingcommandsfor reuse looks fine.packages/next/lib/get-project-dir.ts (1)
24-33: Typo suggestion path reads well.
The error message is clear and the early exit is consistent with existing ENOENT handling.test/integration/cli/test/index.test.js (1)
61-79: Good coverage for typo suggestions.
The test matrix is clear and aligns with the new CLI behavior.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| import { commands } from '../bin/next' | ||
| import * as Log from '../build/output/log' | ||
| import { detectTypo } from './detect-typo' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find all call sites of getProjectDir and all imports of it
rg -n "getProjectDir\s*\(" --type=ts --type=tsx | head -30Repository: Signal65/next.js-CodeRabbit
Length of output: 98
🏁 Script executed:
# Find all imports of get-project-dir module
rg -n "from ['\"].*get-project-dir['\"]" --type=ts --type=tsxRepository: Signal65/next.js-CodeRabbit
Length of output: 98
🏁 Script executed:
# Check the bin/next file to understand what it does
cat -n packages/next/bin/nextRepository: Signal65/next.js-CodeRabbit
Length of output: 125
🏁 Script executed:
# Also check the actual get-project-dir.ts file to see full context
cat -n packages/next/lib/get-project-dir.tsRepository: Signal65/next.js-CodeRabbit
Length of output: 1579
🏁 Script executed:
# Find the bin/next file (may be .js or .ts)
find packages/next/bin -type f 2>/dev/null | head -20Repository: Signal65/next.js-CodeRabbit
Length of output: 96
🏁 Script executed:
# List files in bin directory
ls -la packages/next/bin/ 2>/dev/null || echo "Directory listing failed"Repository: Signal65/next.js-CodeRabbit
Length of output: 241
🏁 Script executed:
# Use git to find bin files
git ls-files packages/next/bin/ 2>/dev/null | head -20Repository: Signal65/next.js-CodeRabbit
Length of output: 96
🏁 Script executed:
# Search for getProjectDir usages without type filters
rg -n "getProjectDir" packages/next --max-count=50Repository: Signal65/next.js-CodeRabbit
Length of output: 974
🏁 Script executed:
cat -n packages/next/bin/next.tsRepository: Signal65/next.js-CodeRabbit
Length of output: 5679
🏁 Script executed:
# Check if there are any side effects at top level before the 'commands' export
head -100 packages/next/bin/next.ts | cat -nRepository: Signal65/next.js-CodeRabbit
Length of output: 3804
🏁 Script executed:
# Verify circular dependency by checking if cli/next-build imports get-project-dir
head -20 packages/next/cli/next-build.ts | grep -n "get-project-dir"Repository: Signal65/next.js-CodeRabbit
Length of output: 127
🏁 Script executed:
# Check the structure of the commands object more carefully
sed -n '18,27p' packages/next/bin/next.tsRepository: Signal65/next.js-CodeRabbit
Length of output: 659
Extract the commands list to a side-effect-free module.
Importing ../bin/next pulls in significant side effects: dependency checks (lines 5–14), immediate argument parsing (lines 29–43), potential process.exit() calls on --version or --help (lines 46–72), environment mutation (line 106), process signal handlers (lines 125–126), and most critically, immediate CLI command execution (lines 128–150). This causes unpredictable behavior when getProjectDir is called from library code. Create a separate module (e.g., packages/next/lib/commands.ts) exporting only the command names, and import that in both bin/next.ts and get-project-dir.ts to eliminate side effects and the circular dependency.
🤖 Prompt for AI Agents
In `@packages/next/lib/get-project-dir.ts` around lines 3 - 5, getProjectDir
imports ../bin/next which triggers heavy side effects (dependency checks, CLI
parsing/execution, process.exit, env and signal handlers); extract the simple
commands list into a new side-effect-free module (e.g.,
packages/next/lib/commands.ts) that exports the command names array/object and
import that module from both bin/next.ts and get-project-dir.ts instead of
importing ../bin/next; in practice remove the import of ../bin/next from
get-project-dir.ts, create and export the same `commands` symbol from the new
commands.ts, and update bin/next.ts to import `commands` from commands.ts so
behavior is preserved without executing the CLI side effects.
PR_040
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.