mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-03 01:18:38 +00:00
fix: packageManager in package.json (#10202)
* fix: packageManager in package.json * fix
This commit is contained in:
5
.changeset/new-games-teach.md
Normal file
5
.changeset/new-games-teach.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
fix packageManager in package.json
|
||||
@@ -124,12 +124,20 @@ async function adaptWorkspaceConfig(
|
||||
|
||||
const isMonorepo = fs.existsSync(pnpmWorkspacePath)
|
||||
|
||||
// Update root package.json: strip "packageManager" field to avoid
|
||||
// triggering Corepack, and add "workspaces" for npm/bun/yarn.
|
||||
// Update root package.json: update "packageManager" field for the
|
||||
// target package manager, and add "workspaces" for npm/bun/yarn.
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const packageJsonContent = await fs.readFile(packageJsonPath, "utf8")
|
||||
const packageJson = JSON.parse(packageJsonContent)
|
||||
delete packageJson.packageManager
|
||||
|
||||
if (isMonorepo) {
|
||||
// Monorepo templates use turbo which requires packageManager.
|
||||
// Replace the pnpm value with the target package manager.
|
||||
packageJson.packageManager =
|
||||
await getPackageManagerVersion(packageManager)
|
||||
} else {
|
||||
delete packageJson.packageManager
|
||||
}
|
||||
|
||||
if (isMonorepo) {
|
||||
// Read workspace patterns from pnpm-workspace.yaml.
|
||||
@@ -160,6 +168,16 @@ async function adaptWorkspaceConfig(
|
||||
}
|
||||
}
|
||||
|
||||
// Get the package manager name and version string (e.g. "bun@1.2.0").
|
||||
async function getPackageManagerVersion(packageManager: string) {
|
||||
try {
|
||||
const { stdout } = await execa(packageManager, ["--version"])
|
||||
return `${packageManager}@${stdout.trim()}`
|
||||
} catch {
|
||||
return `${packageManager}@*`
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively find all package.json files and replace workspace: protocol
|
||||
// version specifiers with "*", which npm understands.
|
||||
async function rewriteWorkspaceProtocol(dir: string) {
|
||||
|
||||
@@ -234,7 +234,7 @@ describe("defaultScaffold", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("should strip packageManager field from package.json for non-pnpm", async () => {
|
||||
it("should strip packageManager field from package.json for non-pnpm non-monorepo", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) =>
|
||||
p.toString().includes("package.json")
|
||||
)
|
||||
@@ -279,6 +279,14 @@ describe("defaultScaffold", () => {
|
||||
)
|
||||
}) as any)
|
||||
|
||||
// Mock execa to return a version for bun --version.
|
||||
vi.mocked(execa).mockImplementation(((cmd: string, args: string[]) => {
|
||||
if (cmd === "bun" && args[0] === "--version") {
|
||||
return Promise.resolve({ stdout: "1.2.0" } as any)
|
||||
}
|
||||
return Promise.resolve({ stdout: "", exitCode: 0 } as any)
|
||||
}) as any)
|
||||
|
||||
const template = createTestTemplate()
|
||||
|
||||
await template.scaffold({
|
||||
@@ -300,7 +308,7 @@ describe("defaultScaffold", () => {
|
||||
expect(adaptCall).toBeDefined()
|
||||
const written = JSON.parse(adaptCall![1] as string)
|
||||
expect(written.workspaces).toEqual(["apps/*", "packages/*"])
|
||||
expect(written.packageManager).toBeUndefined()
|
||||
expect(written.packageManager).toBe("bun@1.2.0")
|
||||
})
|
||||
|
||||
it("should rewrite workspace: protocol refs to * for npm monorepo", async () => {
|
||||
@@ -391,6 +399,165 @@ describe("defaultScaffold", () => {
|
||||
expect(vi.mocked(fs.readdir)).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should set packageManager to detected version for monorepo with bun", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) => {
|
||||
const s = p.toString()
|
||||
return s.includes("pnpm-workspace.yaml") || s.includes("package.json")
|
||||
})
|
||||
|
||||
vi.mocked(fs.readFile).mockImplementation(((filePath: string) => {
|
||||
if (filePath.includes("pnpm-workspace.yaml")) {
|
||||
return Promise.resolve("packages:\n - 'apps/*'\n")
|
||||
}
|
||||
return Promise.resolve(
|
||||
JSON.stringify({ name: "my-mono", packageManager: "pnpm@9.0.0" })
|
||||
)
|
||||
}) as any)
|
||||
|
||||
vi.mocked(execa).mockImplementation(((cmd: string, args: string[]) => {
|
||||
if (cmd === "bun" && args[0] === "--version") {
|
||||
return Promise.resolve({ stdout: "1.2.5" } as any)
|
||||
}
|
||||
return Promise.resolve({ stdout: "", exitCode: 0 } as any)
|
||||
}) as any)
|
||||
|
||||
const template = createTestTemplate()
|
||||
|
||||
await template.scaffold({
|
||||
projectPath: "/test/my-app",
|
||||
packageManager: "bun",
|
||||
cwd: "/test",
|
||||
})
|
||||
|
||||
const writeCalls = vi.mocked(fs.writeFile).mock.calls
|
||||
const adaptCall = writeCalls.find(
|
||||
(call) => call[0] === path.join("/test/my-app", "package.json")
|
||||
)
|
||||
expect(adaptCall).toBeDefined()
|
||||
const written = JSON.parse(adaptCall![1] as string)
|
||||
expect(written.packageManager).toBe("bun@1.2.5")
|
||||
})
|
||||
|
||||
it("should set packageManager to detected version for monorepo with npm", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) => {
|
||||
const s = p.toString()
|
||||
return s.includes("pnpm-workspace.yaml") || s.includes("package.json")
|
||||
})
|
||||
|
||||
vi.mocked(fs.readFile).mockImplementation(((filePath: string) => {
|
||||
if (filePath.includes("pnpm-workspace.yaml")) {
|
||||
return Promise.resolve("packages:\n - 'apps/*'\n")
|
||||
}
|
||||
return Promise.resolve(
|
||||
JSON.stringify({ name: "my-mono", packageManager: "pnpm@9.0.0" })
|
||||
)
|
||||
}) as any)
|
||||
|
||||
// Mock readdir for rewriteWorkspaceProtocol.
|
||||
vi.mocked(fs.readdir).mockResolvedValue([] as any)
|
||||
|
||||
vi.mocked(execa).mockImplementation(((cmd: string, args: string[]) => {
|
||||
if (cmd === "npm" && args[0] === "--version") {
|
||||
return Promise.resolve({ stdout: "10.8.1" } as any)
|
||||
}
|
||||
return Promise.resolve({ stdout: "", exitCode: 0 } as any)
|
||||
}) as any)
|
||||
|
||||
const template = createTestTemplate()
|
||||
|
||||
await template.scaffold({
|
||||
projectPath: "/test/my-app",
|
||||
packageManager: "npm",
|
||||
cwd: "/test",
|
||||
})
|
||||
|
||||
const writeCalls = vi.mocked(fs.writeFile).mock.calls
|
||||
const adaptCall = writeCalls.find(
|
||||
(call) => call[0] === path.join("/test/my-app", "package.json")
|
||||
)
|
||||
expect(adaptCall).toBeDefined()
|
||||
const written = JSON.parse(adaptCall![1] as string)
|
||||
expect(written.packageManager).toBe("npm@10.8.1")
|
||||
})
|
||||
|
||||
it("should set packageManager to yarn version for monorepo with yarn", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) => {
|
||||
const s = p.toString()
|
||||
return s.includes("pnpm-workspace.yaml") || s.includes("package.json")
|
||||
})
|
||||
|
||||
vi.mocked(fs.readFile).mockImplementation(((filePath: string) => {
|
||||
if (filePath.includes("pnpm-workspace.yaml")) {
|
||||
return Promise.resolve("packages:\n - 'apps/*'\n")
|
||||
}
|
||||
return Promise.resolve(
|
||||
JSON.stringify({ name: "my-mono", packageManager: "pnpm@9.0.0" })
|
||||
)
|
||||
}) as any)
|
||||
|
||||
vi.mocked(execa).mockImplementation(((cmd: string, args: string[]) => {
|
||||
if (cmd === "yarn" && args[0] === "--version") {
|
||||
return Promise.resolve({ stdout: "4.6.0" } as any)
|
||||
}
|
||||
return Promise.resolve({ stdout: "", exitCode: 0 } as any)
|
||||
}) as any)
|
||||
|
||||
const template = createTestTemplate()
|
||||
|
||||
await template.scaffold({
|
||||
projectPath: "/test/my-app",
|
||||
packageManager: "yarn",
|
||||
cwd: "/test",
|
||||
})
|
||||
|
||||
const writeCalls = vi.mocked(fs.writeFile).mock.calls
|
||||
const adaptCall = writeCalls.find(
|
||||
(call) => call[0] === path.join("/test/my-app", "package.json")
|
||||
)
|
||||
expect(adaptCall).toBeDefined()
|
||||
const written = JSON.parse(adaptCall![1] as string)
|
||||
expect(written.packageManager).toBe("yarn@4.6.0")
|
||||
})
|
||||
|
||||
it("should fallback to wildcard version if version detection fails", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) => {
|
||||
const s = p.toString()
|
||||
return s.includes("pnpm-workspace.yaml") || s.includes("package.json")
|
||||
})
|
||||
|
||||
vi.mocked(fs.readFile).mockImplementation(((filePath: string) => {
|
||||
if (filePath.includes("pnpm-workspace.yaml")) {
|
||||
return Promise.resolve("packages:\n - 'apps/*'\n")
|
||||
}
|
||||
return Promise.resolve(
|
||||
JSON.stringify({ name: "my-mono", packageManager: "pnpm@9.0.0" })
|
||||
)
|
||||
}) as any)
|
||||
|
||||
vi.mocked(execa).mockImplementation(((cmd: string, args: string[]) => {
|
||||
if (args[0] === "--version") {
|
||||
return Promise.reject(new Error("command not found"))
|
||||
}
|
||||
return Promise.resolve({ stdout: "", exitCode: 0 } as any)
|
||||
}) as any)
|
||||
|
||||
const template = createTestTemplate()
|
||||
|
||||
await template.scaffold({
|
||||
projectPath: "/test/my-app",
|
||||
packageManager: "bun",
|
||||
cwd: "/test",
|
||||
})
|
||||
|
||||
const writeCalls = vi.mocked(fs.writeFile).mock.calls
|
||||
const adaptCall = writeCalls.find(
|
||||
(call) => call[0] === path.join("/test/my-app", "package.json")
|
||||
)
|
||||
expect(adaptCall).toBeDefined()
|
||||
const written = JSON.parse(adaptCall![1] as string)
|
||||
expect(written.packageManager).toBe("bun@*")
|
||||
})
|
||||
|
||||
it("should write project name to package.json", async () => {
|
||||
vi.mocked(fs.existsSync).mockImplementation((p: any) =>
|
||||
p.toString().includes("package.json")
|
||||
|
||||
@@ -600,7 +600,7 @@ describe("shadcn init - next-monorepo", () => {
|
||||
// Build a custom init URL with specific options.
|
||||
const registryUrl = process.env.REGISTRY_URL || "http://localhost:4000/r"
|
||||
const baseUrl = registryUrl.replace(/\/r\/?$/, "")
|
||||
const initUrl = `${baseUrl}/init?base=radix&style=nova&baseColor=zinc&theme=zinc&iconLibrary=lucide&font=inter&rtl=false&menuAccent=subtle&menuColor=default&radius=default&template=next`
|
||||
const initUrl = `${baseUrl}/init?base=radix&style=nova&baseColor=zinc&theme=zinc&chartColor=zinc&iconLibrary=lucide&font=inter&rtl=false&menuAccent=subtle&menuColor=default&radius=default&template=next`
|
||||
|
||||
const result = await npxShadcn(
|
||||
testBaseDir,
|
||||
|
||||
Reference in New Issue
Block a user