From 4b4d9c1173253b83be35026ab21852302139e469 Mon Sep 17 00:00:00 2001 From: ziho Date: Mon, 19 Jan 2026 22:28:06 +0900 Subject: [PATCH 1/3] fix: remove root tsconfig fallback and add error handling for package tsconfig resolution --- packages/cli/src/commands/build/index.ts | 69 +++++++++++---------- packages/cli/src/commands/check/index.ts | 64 ++++++++++--------- packages/cli/src/commands/generate/index.ts | 68 +++++++++++--------- packages/cli/src/core/get-ts-config-path.ts | 7 +-- 4 files changed, 108 insertions(+), 100 deletions(-) diff --git a/packages/cli/src/commands/build/index.ts b/packages/cli/src/commands/build/index.ts index 56458f3..bff1a40 100644 --- a/packages/cli/src/commands/build/index.ts +++ b/packages/cli/src/commands/build/index.ts @@ -45,37 +45,41 @@ export class BuildCommand extends Command { for (const pkg of targetPackages) { console.log(`📝 ${pkg.name} processing...`); - const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); - const project = getTsProject(tsConfigPath); - const projectSourceFiles = project.getSourceFiles(); - - const exportSourceFiles = projectSourceFiles.filter(isExportSourceFile); - const exportDeclarationsBySourceFiles = exportSourceFiles.flatMap( - getExportedDeclarationsBySourceFile - ); - const excludeBarrelReExport = excludeBarrelReExports( - exportDeclarationsBySourceFiles - ); - const targets = excludeBarrelReExport.filter((target) => { - return target.jsDoc && hasJSDocTag(target.declaration, "public"); - }); - - const targetsWithJSDoc = targets.map((target) => - parseJSDoc(target, parser) - ); - - const docs = targetsWithJSDoc.map((target) => - generator.generateDocs(target, pkg.location) - ); - - console.log(`Generated ${docs.length} documentation files:`); - for (const doc of docs) { - const outputPath = path.join(outputDir, doc.relativePath); - await fs.mkdir(path.dirname(outputPath), { recursive: true }); - await fs.writeFile(outputPath, doc.content); - console.log(` - ${doc.relativePath}`); - - manifestManager.add(doc.relativePath); + try { + const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); + const project = getTsProject(tsConfigPath); + const projectSourceFiles = project.getSourceFiles(); + + const exportSourceFiles = projectSourceFiles.filter(isExportSourceFile); + const exportDeclarationsBySourceFiles = exportSourceFiles.flatMap( + getExportedDeclarationsBySourceFile + ); + const excludeBarrelReExport = excludeBarrelReExports( + exportDeclarationsBySourceFiles + ); + const targets = excludeBarrelReExport.filter((target) => { + return target.jsDoc && hasJSDocTag(target.declaration, "public"); + }); + + const targetsWithJSDoc = targets.map((target) => + parseJSDoc(target, parser) + ); + + const docs = targetsWithJSDoc.map((target) => + generator.generateDocs(target, pkg.location) + ); + + console.log(`Generated ${docs.length} documentation files:`); + for (const doc of docs) { + const outputPath = path.join(outputDir, doc.relativePath); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, doc.content); + console.log(` - ${doc.relativePath}`); + + manifestManager.add(doc.relativePath); + } + } catch (error) { + console.error(`Failed to build ${pkg.name}: ${error instanceof Error ? error.message : String(error)}`); } } @@ -133,8 +137,7 @@ async function loadContext() { ); } catch (error) { console.error( - `❌ Failed to load plugins: ${ - error instanceof Error ? error.message : String(error) + `❌ Failed to load plugins: ${error instanceof Error ? error.message : String(error) }` ); } diff --git a/packages/cli/src/commands/check/index.ts b/packages/cli/src/commands/check/index.ts index 20cdc74..87d82c6 100644 --- a/packages/cli/src/commands/check/index.ts +++ b/packages/cli/src/commands/check/index.ts @@ -30,40 +30,44 @@ export class CheckCommand extends Command { console.log(`📝 ${pkg.name} processing...`); const packagePath = path.resolve(projectConfig.root, pkg.location); - const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); - const project = getTsProject(tsConfigPath); + try { + const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); + const project = getTsProject(tsConfigPath); - const entryPoints = - checkConfig.entryPoints ?? getPackageEntryPoints(packagePath); + const entryPoints = + checkConfig.entryPoints ?? getPackageEntryPoints(packagePath); - const sourceFiles = project.getSourceFiles(); - const entryPointFiles = sourceFiles.filter((file) => { - const filePath = file.getFilePath(); - return entryPoints.some((entryPoint) => filePath.includes(entryPoint)); - }); - - const exportSourceFiles = entryPointFiles.filter(isExportSourceFile); - const exportDeclarationsBySourceFiles = exportSourceFiles.flatMap( - getExportedDeclarationsBySourceFile - ); - const excludeBarrelReExport = excludeBarrelReExports( - exportDeclarationsBySourceFiles - ); - const missingJSDocExports = excludeBarrelReExport.filter((target) => { - return !hasJSDocTag(target.declaration, "public"); - }); + const sourceFiles = project.getSourceFiles(); + const entryPointFiles = sourceFiles.filter((file) => { + const filePath = file.getFilePath(); + return entryPoints.some((entryPoint) => filePath.includes(entryPoint)); + }); - if (missingJSDocExports.length > 0) { - console.log(`❌ ${pkg.name} has missing JSDoc:`); - missingJSDocExports.forEach((exportInfo) => { - const relativePath = path.relative( - projectConfig.root, - exportInfo.filePath - ); - console.log(` - ${relativePath}:${exportInfo.symbolName}`); + const exportSourceFiles = entryPointFiles.filter(isExportSourceFile); + const exportDeclarationsBySourceFiles = exportSourceFiles.flatMap( + getExportedDeclarationsBySourceFile + ); + const excludeBarrelReExport = excludeBarrelReExports( + exportDeclarationsBySourceFiles + ); + const missingJSDocExports = excludeBarrelReExport.filter((target) => { + return !hasJSDocTag(target.declaration, "public"); }); - } else { - console.log(`✅ ${pkg.name} has JSDoc for all exports`); + + if (missingJSDocExports.length > 0) { + console.log(`❌ ${pkg.name} has missing JSDoc:`); + missingJSDocExports.forEach((exportInfo) => { + const relativePath = path.relative( + projectConfig.root, + exportInfo.filePath + ); + console.log(` - ${relativePath}:${exportInfo.symbolName}`); + }); + } else { + console.log(`✅ ${pkg.name} has JSDoc for all exports`); + } + } catch (error) { + console.error(`Failed to check ${pkg.name}: ${error instanceof Error ? error.message : String(error)}`); } } diff --git a/packages/cli/src/commands/generate/index.ts b/packages/cli/src/commands/generate/index.ts index ec6f01c..46cea5b 100644 --- a/packages/cli/src/commands/generate/index.ts +++ b/packages/cli/src/commands/generate/index.ts @@ -38,37 +38,43 @@ export class GenerateCommand extends Command { const allGenerateTargets = targetPackages.flatMap((pkg) => { console.log(`📝 ${pkg.name} processing...`); - const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); - const project = getTsProject(tsConfigPath); - const projectSourceFiles = project.getSourceFiles(); - - const exportDeclarationsBySourceFiles = projectSourceFiles.flatMap( - getExportedDeclarationsBySourceFile - ); - - const excludeBarrelReExport = excludeBarrelReExports( - exportDeclarationsBySourceFiles - ); - - const generateTargets = excludeBarrelReExport.filter((target) => { - return target.jsDoc && hasJSDocTag(target.declaration, "generate"); - }); - - return generateTargets - .map((target) => { - const signature = extractSignature(target.declaration); - if (!signature) { - return null; - } - - return { - ...target, - signature, - pkg, - project, - }; - }) - .filter((target): target is GenerateTarget => target !== null); + try { + const tsConfigPath = getTsConfigPath(projectConfig.root, pkg.location); + const project = getTsProject(tsConfigPath); + const projectSourceFiles = project.getSourceFiles(); + + const exportDeclarationsBySourceFiles = projectSourceFiles.flatMap( + getExportedDeclarationsBySourceFile + ); + + const excludeBarrelReExport = excludeBarrelReExports( + exportDeclarationsBySourceFiles + ); + + const generateTargets = excludeBarrelReExport.filter((target) => { + return target.jsDoc && hasJSDocTag(target.declaration, "generate"); + }); + + return generateTargets + .map((target) => { + const signature = extractSignature(target.declaration); + if (signature == null) { + return null; + } + + return { + ...target, + signature, + pkg, + project, + }; + }) + .filter((target): target is GenerateTarget => target != null); + } catch (error) { + console.error(`Failed to process ${pkg.name}: ${error instanceof Error ? error.message : String(error)}`); + + return []; + } }); if (allGenerateTargets.length === 0) { diff --git a/packages/cli/src/core/get-ts-config-path.ts b/packages/cli/src/core/get-ts-config-path.ts index b813aa9..eb60acb 100644 --- a/packages/cli/src/core/get-ts-config-path.ts +++ b/packages/cli/src/core/get-ts-config-path.ts @@ -12,10 +12,5 @@ export function getTsConfigPath(root: string, pkg: string) { return buildConfigPath; } - const rootConfigPath = path.join(root, "tsconfig.json"); - if (existsSync(rootConfigPath)) { - return rootConfigPath; - } - - throw new Error(`tsconfig.json not found in ${root} or ${pkg}`); + throw new Error(`tsconfig.json not found in ${pkg}`); } From e0ff2a25cdb1f9718e2afb2d8f6a8a9fa0d6f093 Mon Sep 17 00:00:00 2001 From: ziho Date: Mon, 19 Jan 2026 22:42:30 +0900 Subject: [PATCH 2/3] empty commit From b4b1309e7c37be324eec7c7dff91fdaab8e5285c Mon Sep 17 00:00:00 2001 From: ziho Date: Mon, 19 Jan 2026 22:50:23 +0900 Subject: [PATCH 3/3] test: update getTsConfigPath test to throw error for non-existent package tsconfig --- packages/cli/src/tests/core/get-ts-config-path.spec.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/tests/core/get-ts-config-path.spec.ts b/packages/cli/src/tests/core/get-ts-config-path.spec.ts index 79cf43e..59a8ced 100644 --- a/packages/cli/src/tests/core/get-ts-config-path.spec.ts +++ b/packages/cli/src/tests/core/get-ts-config-path.spec.ts @@ -28,14 +28,11 @@ describe("getTsConfigPath", () => { expect(tsConfigPath).toBe(expectedPath); }); - it("should return root tsconfig.json path when package tsconfig doesn't exist", async () => { + it("should throw error when package tsconfig doesn't exist", async () => { const projectRoot = workspace.root; const packageLocation = "packages/non-existent"; - const tsConfigPath = getTsConfigPath(projectRoot, packageLocation); - const expectedPath = path.join(projectRoot, "tsconfig.json"); - - expect(tsConfigPath).toBe(expectedPath); + expect(() => getTsConfigPath(projectRoot, packageLocation)).toThrow(); }); it("should handle absolute paths correctly", async () => {