From 00a8b9b0fcb6fd703759ebb87a2fe9a49bcb31b3 Mon Sep 17 00:00:00 2001 From: oritwoen <18102267+oritwoen@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:24:27 +0100 Subject: [PATCH] fix(author): support direct workspace paths --- src/commands/author.ts | 19 +++++++++++++++++++ test/unit/author.test.ts | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/commands/author.ts b/src/commands/author.ts index 3a05263b..7c40c943 100644 --- a/src/commands/author.ts +++ b/src/commands/author.ts @@ -102,6 +102,25 @@ export function detectMonorepoPackages(cwd: string): MonorepoPackage[] | null { if (!existsSync(scanDir)) continue + const directResult = readPackageJsonSafe(join(scanDir, 'package.json')) + if (directResult) { + const directPkg = directResult.parsed as Record + 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 })) { if (!entry.isDirectory()) continue diff --git a/test/unit/author.test.ts b/test/unit/author.test.ts index 4862903e..b009cf9d 100644 --- a/test/unit/author.test.ts +++ b/test/unit/author.test.ts @@ -195,6 +195,42 @@ describe('author', () => { expect(result![0].name).toBe('lib-a') }) + it('detects workspace entries that point to a package directory directly', async () => { + const { existsSync, readFileSync, readdirSync } = await import('node:fs') + + vi.mocked(existsSync).mockImplementation((p: any) => { + const s = String(p) + if (s === '/project/package.json') + return true + if (s === '/project/packages/foo') + return true + if (s === '/project/packages/foo/package.json') + return true + return false + }) + + vi.mocked(readFileSync).mockImplementation((p: any) => { + const s = String(p) + if (s === '/project/package.json') + return JSON.stringify({ private: true, workspaces: ['packages/foo'] }) + if (s === '/project/packages/foo/package.json') + return JSON.stringify({ name: 'foo', version: '1.2.3' }) + return '' + }) + + vi.mocked(readdirSync).mockReturnValue([]) + + const { detectMonorepoPackages } = await import('../../src/commands/author') + const result = detectMonorepoPackages('/project') + + expect(result).toHaveLength(1) + expect(result![0]).toMatchObject({ + name: 'foo', + version: '1.2.3', + dir: '/project/packages/foo', + }) + }) + it('resolves repository URL from object form', async () => { const { existsSync, readFileSync, readdirSync } = await import('node:fs')