From d5bf0018fda42faeb314dc3edc87b8cd7c0354c6 Mon Sep 17 00:00:00 2001 From: shadcn Date: Wed, 13 Nov 2024 15:15:22 +0400 Subject: [PATCH] fix(shadcn): handling of tsconfig aliases (#5813) * fix(shadcn): handling of tsconfig aliases * chore: add changeset --- .changeset/fresh-turtles-cheat.md | 5 +++ packages/shadcn/src/utils/get-project-info.ts | 44 ++++++++++++++----- 2 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 .changeset/fresh-turtles-cheat.md diff --git a/.changeset/fresh-turtles-cheat.md b/.changeset/fresh-turtles-cheat.md new file mode 100644 index 00000000000..c338eb0c79b --- /dev/null +++ b/.changeset/fresh-turtles-cheat.md @@ -0,0 +1,5 @@ +--- +"shadcn": patch +--- + +fix handling of aliases diff --git a/packages/shadcn/src/utils/get-project-info.ts b/packages/shadcn/src/utils/get-project-info.ts index 997ed2ade73..741c9c6b505 100644 --- a/packages/shadcn/src/utils/get-project-info.ts +++ b/packages/shadcn/src/utils/get-project-info.ts @@ -10,6 +10,7 @@ import { getPackageInfo } from "@/src/utils/get-package-info" import fg from "fast-glob" import fs from "fs-extra" import { loadConfig } from "tsconfig-paths" +import { z } from "zod" type ProjectInfo = { framework: Framework @@ -29,6 +30,12 @@ const PROJECT_SHARED_IGNORE = [ "build", ] +const TS_CONFIG_SCHEMA = z.object({ + compilerOptions: z.object({ + paths: z.record(z.string().or(z.array(z.string()))), + }), +}) + export async function getProjectInfo(cwd: string): Promise { const [ configFiles, @@ -153,7 +160,10 @@ export async function getTailwindConfigFile(cwd: string) { export async function getTsConfigAliasPrefix(cwd: string) { const tsConfig = await loadConfig(cwd) - if (tsConfig?.resultType === "failed" || !tsConfig?.paths) { + if ( + tsConfig?.resultType === "failed" || + !Object.entries(tsConfig?.paths).length + ) { return null } @@ -169,7 +179,8 @@ export async function getTsConfigAliasPrefix(cwd: string) { } } - return null + // Use the first alias as the prefix. + return Object.keys(tsConfig?.paths)?.[0].replace(/\/\*$/, "") ?? null } export async function isTypeScriptProject(cwd: string) { @@ -182,19 +193,30 @@ export async function isTypeScriptProject(cwd: string) { return files.length > 0 } -export async function getTsConfig() { - try { - const tsconfigPath = path.join("tsconfig.json") - const tsconfig = await fs.readJSON(tsconfigPath) +export async function getTsConfig(cwd: string) { + for (const fallback of [ + "tsconfig.json", + "tsconfig.web.json", + "tsconfig.app.json", + ]) { + const filePath = path.resolve(cwd, fallback) + if (!(await fs.pathExists(filePath))) { + continue + } - if (!tsconfig) { - throw new Error("tsconfig.json is missing") + // We can't use fs.readJSON because it doesn't support comments. + const contents = await fs.readFile(filePath, "utf8") + const cleanedContents = contents.replace(/\/\*\s*\*\//g, "") + const result = TS_CONFIG_SCHEMA.safeParse(JSON.parse(cleanedContents)) + + if (result.error) { + continue } - return tsconfig - } catch (error) { - return null + return result.data } + + return null } export async function getProjectConfig(