Skip to content

Commit 54ca6ce

Browse files
committed
fix(#441): detect package manager for shadcn
1 parent 3796258 commit 54ca6ce

File tree

4 files changed

+154
-91
lines changed

4 files changed

+154
-91
lines changed

apps/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"execa": "^7.2.0",
6060
"log-symbols": "^7.0.1",
6161
"ora": "^6.1.2",
62+
"package-manager-detector": "^1.3.0",
6263
"tsup": "^8.2.4",
6364
"tsx": "^4.19.1",
6465
"typescript": "^5.8.3",

apps/cli/src/services/commands/add.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { Effect, Layer } from "effect"
21
import { CliOptions } from "@cli/contexts/cli-options.js"
3-
import { Doctor } from "@cli/services/commands/doctor.js"
4-
import { ProjectConfig } from "../project-config.js"
5-
import { Prompt } from "@effect/cli"
62
import { PROJECT_MANIFEST } from "@cli/project-manifest.js"
3+
import { Doctor } from "@cli/services/commands/doctor.js"
74
import { runCommand } from "@cli/utils/run-command.js"
5+
import { Prompt } from "@effect/cli"
6+
import { Effect, Layer } from "effect"
7+
import { PackageManager } from "../package-manager.js"
8+
import { ProjectConfig } from "../project-config.js"
89

910
type AddOptions = {
1011
cwd: string
@@ -16,9 +17,11 @@ type AddOptions = {
1617
}
1718

1819
class Add extends Effect.Service<Add>()("Add", {
20+
dependencies: [PackageManager.Default],
1921
effect: Effect.gen(function* () {
2022
const doctor = yield* Doctor
2123
const projectConfig = yield* ProjectConfig
24+
const packageManager = yield* PackageManager
2225

2326
return {
2427
run: (options: AddOptions) =>
@@ -60,11 +63,20 @@ class Add extends Effect.Service<Add>()("Add", {
6063

6164
const shadcnOptions = toShadcnOptions(options)
6265

63-
const commandArgs = ["--yes", "shadcn@latest", "add", ...shadcnOptions, ...componentUrls]
66+
const binaryRunner = yield* packageManager.getBinaryRunner(options.cwd)
67+
68+
const commandArgs = [
69+
binaryRunner[1],
70+
"--yes",
71+
"shadcn@latest",
72+
"add",
73+
...shadcnOptions,
74+
...componentUrls
75+
].filter((option) => option !== undefined)
6476

65-
yield* Effect.logDebug(`Running command: npx ${commandArgs.join(" ")}`)
77+
yield* Effect.logDebug(`Running command: ${binaryRunner[0]} ${commandArgs.join(" ")}`)
6678

67-
yield* runCommand("npx", commandArgs, {
79+
yield* runCommand(binaryRunner[0], commandArgs, {
6880
cwd: options.cwd,
6981
stdio: "inherit"
7082
})
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Effect } from "effect"
2+
import { detect } from "package-manager-detector"
3+
4+
const PACKAGE_MANAGERS = ["npm", "bun", "pnpm", "yarn"] as const
5+
6+
const BINARY_RUNNERS = { npm: ["npx"], bun: ["bunx", "--bun"], pnpm: ["pnpm", "dlx"], yarn: ["yarn"] } as const
7+
8+
const detectPackageManager = (cwd: string) =>
9+
Effect.tryPromise({
10+
try: () => {
11+
return detect({
12+
cwd,
13+
strategies: ["install-metadata", "lockfile", "packageManager-field", "devEngines-field"]
14+
})
15+
},
16+
catch: () => new Error("Failed to get package manager")
17+
})
18+
19+
const getPackageManager = (cwd: string) =>
20+
Effect.gen(function* () {
21+
const pm = yield* detectPackageManager(cwd)
22+
if (!pm) {
23+
return "npm"
24+
}
25+
const name = PACKAGE_MANAGERS.find((name) => pm.name.startsWith(name) || pm.agent.startsWith(name)) ?? "npm"
26+
return name
27+
})
28+
const getBinaryRunner = (cwd: string) =>
29+
Effect.gen(function* () {
30+
const pm = yield* getPackageManager(cwd)
31+
return BINARY_RUNNERS[pm]
32+
})
33+
34+
class PackageManager extends Effect.Service<PackageManager>()("PackageManager", {
35+
succeed: {
36+
detectPackageManager,
37+
getPackageManager,
38+
getBinaryRunner
39+
}
40+
}) {}
41+
42+
export { PackageManager }

0 commit comments

Comments
 (0)