fix(author): support direct workspace paths#56
Conversation
📝 WalkthroughWalkthroughModified monorepo package discovery to optimize workspace pattern handling. When a workspace pattern directory itself is a valid package, it's directly registered; otherwise, child directories are enumerated. Package validation checks for non-private status and presence of a name field, with repository URLs normalized from Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
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 docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/commands/author.ts`:
- Around line 105-123: The direct package.json detection inside
detectMonorepoPackages incorrectly runs for glob workspace entries and causes
parent dirs like "packages" to short-circuit child package discovery; before
calling readPackageJsonSafe(scanDir + '/package.json') add a guard that skips
the directResult check when the original workspace pattern contains glob
characters (e.g., '*' '?' or '[') — use the workspace pattern variable used to
derive scanDir (or keep the pattern in scope) and only perform the directPkg
logic (the directResult/directPkg branch that pushes to packages and continues)
when the pattern is a non-glob literal; this preserves the existing behavior for
literal workspace entries while preventing glob parents from swallowing child
packages.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fbe135a1-7fc9-4cb2-b283-612eaef799a6
📒 Files selected for processing (2)
src/commands/author.tstest/unit/author.test.ts
| const directResult = readPackageJsonSafe(join(scanDir, 'package.json')) | ||
| if (directResult) { | ||
| const directPkg = directResult.parsed as Record<string, any> | ||
| if (!directPkg.private && directPkg.name) { | ||
| const repoUrl = typeof directPkg.repository === 'string' | ||
| ? directPkg.repository | ||
| : directPkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '') | ||
|
|
||
| packages.push({ | ||
| name: directPkg.name, | ||
| version: directPkg.version || '0.0.0', | ||
| description: directPkg.description, | ||
| repoUrl, | ||
| dir: scanDir, | ||
| }) | ||
| continue | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Guard direct package detection to non-glob workspace entries.
Line 105 runs direct scanDir/package.json detection for every workspace pattern. For glob patterns (e.g., packages/*), if packages/package.json exists, Line 120 continues and child packages are skipped.
This can cause detectMonorepoPackages() to miss valid workspace packages.
Proposed fix
for (const pattern of patterns) {
// Expand simple glob: "packages/*" → scan packages/*/package.json
const base = pattern.replace(/\/?\*+$/, '')
const scanDir = resolve(cwd, base)
+ const isGlobPattern = pattern.includes('*')
if (!existsSync(scanDir))
continue
- const directResult = readPackageJsonSafe(join(scanDir, 'package.json'))
- if (directResult) {
- const directPkg = directResult.parsed as Record<string, any>
- if (!directPkg.private && directPkg.name) {
- const repoUrl = typeof directPkg.repository === 'string'
- ? directPkg.repository
- : directPkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '')
-
- packages.push({
- name: directPkg.name,
- version: directPkg.version || '0.0.0',
- description: directPkg.description,
- repoUrl,
- dir: scanDir,
- })
- continue
- }
- }
+ if (!isGlobPattern) {
+ const directResult = readPackageJsonSafe(join(scanDir, 'package.json'))
+ if (directResult) {
+ const directPkg = directResult.parsed as Record<string, any>
+ if (!directPkg.private && directPkg.name) {
+ const repoUrl = typeof directPkg.repository === 'string'
+ ? directPkg.repository
+ : directPkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '')
+
+ packages.push({
+ name: directPkg.name,
+ version: directPkg.version || '0.0.0',
+ description: directPkg.description,
+ repoUrl,
+ dir: scanDir,
+ })
+ continue
+ }
+ }
+ }
for (const entry of readdirSync(scanDir, { withFileTypes: true })) {📝 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.
| const directResult = readPackageJsonSafe(join(scanDir, 'package.json')) | |
| if (directResult) { | |
| const directPkg = directResult.parsed as Record<string, any> | |
| if (!directPkg.private && directPkg.name) { | |
| const repoUrl = typeof directPkg.repository === 'string' | |
| ? directPkg.repository | |
| : directPkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '') | |
| packages.push({ | |
| name: directPkg.name, | |
| version: directPkg.version || '0.0.0', | |
| description: directPkg.description, | |
| repoUrl, | |
| dir: scanDir, | |
| }) | |
| continue | |
| } | |
| } | |
| const scanDir = resolve(cwd, base) | |
| const isGlobPattern = pattern.includes('*') | |
| if (!existsSync(scanDir)) | |
| continue | |
| if (!isGlobPattern) { | |
| const directResult = readPackageJsonSafe(join(scanDir, 'package.json')) | |
| if (directResult) { | |
| const directPkg = directResult.parsed as Record<string, any> | |
| if (!directPkg.private && directPkg.name) { | |
| const repoUrl = typeof directPkg.repository === 'string' | |
| ? directPkg.repository | |
| : directPkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '') | |
| packages.push({ | |
| name: directPkg.name, | |
| version: directPkg.version || '0.0.0', | |
| description: directPkg.description, | |
| repoUrl, | |
| dir: scanDir, | |
| }) | |
| continue | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/commands/author.ts` around lines 105 - 123, The direct package.json
detection inside detectMonorepoPackages incorrectly runs for glob workspace
entries and causes parent dirs like "packages" to short-circuit child package
discovery; before calling readPackageJsonSafe(scanDir + '/package.json') add a
guard that skips the directResult check when the original workspace pattern
contains glob characters (e.g., '*' '?' or '[') — use the workspace pattern
variable used to derive scanDir (or keep the pattern in scope) and only perform
the directPkg logic (the directResult/directPkg branch that pushes to packages
and continues) when the pattern is a non-glob literal; this preserves the
existing behavior for literal workspace entries while preventing glob parents
from swallowing child packages.
Description
Direct workspace entries like
packages/foowere being skipped bydetectMonorepoPackages(). The author flow only scanned child directories under each workspace pattern, so exact package paths never resolved andskilld authormissed those packages. This checksscanDir/package.jsonfirst, then falls back to the existing child-directory scan for glob patterns likepackages/*.Linked Issues
N/A
Additional context
Added a unit test for
workspaces: ['packages/foo']. Verified withpnpm vitest run test/unit/author.test.ts,pnpm typecheck, andpnpm lint.Summary by CodeRabbit
Release Notes
Improvements
Tests