Skip to content

Commit e036d6b

Browse files
committed
Add support for Bun
1 parent c7c63bf commit e036d6b

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

src/detectPackageManager.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import chalk from "chalk"
44
import process from "process"
55
import findWorkspaceRoot from "find-yarn-workspace-root"
66

7-
export type PackageManager = "yarn" | "npm" | "npm-shrinkwrap"
7+
export type PackageManager = "yarn" | "npm" | "npm-shrinkwrap" | "bun"
88

99
function printNoYarnLockfileError() {
1010
console.log(`
@@ -17,9 +17,9 @@ ${chalk.red.bold("**ERROR**")} ${chalk.red(
1717
function printNoLockfilesError() {
1818
console.log(`
1919
${chalk.red.bold("**ERROR**")} ${chalk.red(
20-
`No package-lock.json, npm-shrinkwrap.json, or yarn.lock file.
20+
`No package-lock.json, npm-shrinkwrap.json, yarn.lock, or bun.lockb file.
2121
22-
You must use either npm@>=5, yarn, or npm-shrinkwrap to manage this project's
22+
You must use either npm@>=5, yarn, npm-shrinkwrap, or bun to manage this project's
2323
dependencies.`,
2424
)}
2525
`)
@@ -47,7 +47,13 @@ export const detectPackageManager = (
4747
const shrinkWrapExists = fs.existsSync(
4848
join(appRootPath, "npm-shrinkwrap.json"),
4949
)
50-
const yarnLockExists = fs.existsSync(join(appRootPath, "yarn.lock"))
50+
const yarnLockExists = fs.existsSync(
51+
join(findWorkspaceRoot() ?? appRootPath, "pnpm-lock.yaml"),
52+
)
53+
// Bun workspaces seem to work the same as yarn workspaces - https://bun.sh/docs/install/workspaces
54+
const bunLockbExists = fs.existsSync(
55+
join(findWorkspaceRoot() ?? appRootPath, "bun.lockb"),
56+
)
5157
if ((packageLockExists || shrinkWrapExists) && yarnLockExists) {
5258
if (overridePackageManager) {
5359
return overridePackageManager
@@ -62,8 +68,10 @@ export const detectPackageManager = (
6268
} else {
6369
return shrinkWrapExists ? "npm-shrinkwrap" : "npm"
6470
}
65-
} else if (yarnLockExists || findWorkspaceRoot()) {
71+
} else if (yarnLockExists) {
6672
return "yarn"
73+
} else if (bunLockbExists) {
74+
return "bun"
6775
} else {
6876
printNoLockfilesError()
6977
process.exit(1)

src/getPackageResolution.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import yaml from "yaml"
77
import findWorkspaceRoot from "find-yarn-workspace-root"
88
import { getPackageVersion } from "./getPackageVersion"
99
import { coerceSemVer } from "./coerceSemVer"
10+
import { parseBunLockfile } from "./parseBunLockfile"
1011

1112
export function getPackageResolution({
1213
packageDetails,
@@ -17,24 +18,32 @@ export function getPackageResolution({
1718
packageManager: PackageManager
1819
appPath: string
1920
}) {
20-
if (packageManager === "yarn") {
21-
let lockFilePath = "yarn.lock"
21+
if (packageManager === "yarn" || packageManager === "bun") {
22+
const isBun = packageManager === "bun"
23+
const lockFileName = isBun ? "bun.lockb" : "yarn.lock"
24+
let lockFilePath = lockFileName
2225
if (!existsSync(lockFilePath)) {
2326
const workspaceRoot = findWorkspaceRoot()
2427
if (!workspaceRoot) {
25-
throw new Error("Can't find yarn.lock file")
28+
throw new Error(`Can't find ${lockFileName} file`)
2629
}
27-
lockFilePath = join(workspaceRoot, "yarn.lock")
30+
lockFilePath = join(workspaceRoot, lockFilePath)
2831
}
2932
if (!existsSync(lockFilePath)) {
30-
throw new Error("Can't find yarn.lock file")
33+
throw new Error(`Can't find ${lockFileName} file`)
3134
}
32-
const lockFileString = readFileSync(lockFilePath).toString()
35+
const lockFileString = isBun
36+
? parseBunLockfile(lockFilePath)
37+
: readFileSync(lockFilePath).toString()
3338
let appLockFile
3439
if (lockFileString.includes("yarn lockfile v1")) {
3540
const parsedYarnLockFile = parseYarnLockFile(lockFileString)
3641
if (parsedYarnLockFile.type !== "success") {
37-
throw new Error("Could not parse yarn v1 lock file")
42+
throw new Error(
43+
`Could not parse yarn v1 lock file ${
44+
isBun ? "- was originally a bun.lockb file" : ""
45+
}`,
46+
)
3847
} else {
3948
appLockFile = parsedYarnLockFile.object
4049
}
@@ -43,7 +52,11 @@ export function getPackageResolution({
4352
appLockFile = yaml.parse(lockFileString)
4453
} catch (e) {
4554
console.log(e)
46-
throw new Error("Could not parse yarn v2 lock file")
55+
throw new Error(
56+
`Could not parse yarn v2 lock file ${
57+
isBun ? "- was originally a bun.lockb file (should not happen)" : ""
58+
}`,
59+
)
4760
}
4861
}
4962

src/parseBunLockfile.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { spawnSync } from "child_process"
2+
3+
// From https://github.com/oven-sh/bun/blob/ffe4f561a3af53b9f5a41c182de55d7199b5d692/packages/bun-vscode/src/features/lockfile.ts#L39,
4+
// rewritten to use spawnSync instead of spawn.
5+
export function parseBunLockfile(lockFilePath: string): string {
6+
const process = spawnSync("bun", [lockFilePath], {
7+
stdio: ["ignore", "pipe", "pipe"],
8+
})
9+
if (process.status !== 0) {
10+
throw new Error(
11+
`Bun exited with code: ${process.status}\n${process.stderr.toString()}`,
12+
)
13+
}
14+
return process.stdout.toString()
15+
}

0 commit comments

Comments
 (0)