Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support bun package manager #7074

Merged
merged 10 commits into from
Aug 16, 2023
6 changes: 6 additions & 0 deletions .changeset/popular-trains-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"create-remix": minor
"@remix-run/dev": minor
---

Support bun package manager
4 changes: 3 additions & 1 deletion docs/other-api/create-remix.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ npx create-remix@latest --help

### Package managers

`create-remix` can also be invoked using the `create` command of various package managers, allowing you to choose between npm, Yarn and pnpm for managing the install process.
`create-remix` can also be invoked using various package managers, allowing you to choose between npm, Yarn, pnpm, and Bun for managing the install process.

```sh
npm create remix@latest <projectDir>
# or
yarn create remix <projectDir>
# or
pnpm create remix <projectDir>
# or
bunx create-remix <projectDir>
```

### `create-remix --template`
Expand Down
33 changes: 33 additions & 0 deletions packages/create-remix/__tests__/create-remix-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,39 @@ describe("create-remix CLI", () => {
process.env.npm_config_user_agent = originalUserAgent;
});

it("recognizes when Bun was used to run the command", async () => {
let originalUserAgent = process.env.npm_config_user_agent;
process.env.npm_config_user_agent =
"bun/0.7.0 npm/? node/v14.17.0 linux x64";

let projectDir = getProjectDir("bun-create-from-user-agent");

let execa = require("execa");
execa.mockImplementation(async () => {});

// Suppress terminal output
let stdoutMock = jest
.spyOn(process.stdout, "write")
.mockImplementation(() => true);

await createRemix([
projectDir,
"--template",
path.join(__dirname, "fixtures", "blank"),
"--no-git-init",
"--yes",
]);

stdoutMock.mockReset();

expect(execa).toHaveBeenCalledWith(
"bun",
expect.arrayContaining(["install"]),
expect.anything()
);
process.env.npm_config_user_agent = originalUserAgent;
});

it("supports specifying the package manager, regardless of user agent", async () => {
let originalUserAgent = process.env.npm_config_user_agent;
process.env.npm_config_user_agent =
Expand Down
5 changes: 3 additions & 2 deletions packages/create-remix/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ async function getContext(argv: string[]): Promise<Context> {
noMotion,
pkgManager: validatePackageManager(
pkgManager ??
// npm, pnpm and Yarn set the user agent environment variable that can be used
// npm, pnpm, Yarn, and Bun set the user agent environment variable that can be used
// to determine which package manager ran the command.
(process.env.npm_config_user_agent ?? "npm").split("/")[0]
),
Expand Down Expand Up @@ -606,12 +606,13 @@ function isEmpty(dirPath: string) {
return conflicts.length === 0;
}

type PackageManager = "npm" | "yarn" | "pnpm";
type PackageManager = "npm" | "yarn" | "pnpm" | "bun";

const packageManagerExecScript: Record<PackageManager, string> = {
npm: "npx",
yarn: "yarn",
pnpm: "pnpm exec",
bun: "bunx",
};

function validatePackageManager(pkgManager: string): PackageManager {
Expand Down
3 changes: 2 additions & 1 deletion packages/remix-dev/cli/detectPackageManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type PackageManager = "npm" | "pnpm" | "yarn";
type PackageManager = "npm" | "pnpm" | "yarn" | "bun";

/**
* Determine which package manager the user prefers.
Expand All @@ -15,6 +15,7 @@ export const detectPackageManager = (): PackageManager | undefined => {
if (pkgManager === "npm") return "npm";
if (pkgManager === "pnpm") return "pnpm";
if (pkgManager === "yarn") return "yarn";
if (pkgManager === "bun") return "bun";
return undefined;
} catch {
return undefined;
Expand Down
4 changes: 4 additions & 0 deletions packages/remix-dev/devServer_unstable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ let detectBin = async (): Promise<string> => {
let { stdout } = await execa(pkgManager, ["prefix"]);
return path.join(stdout.trim(), "node_modules", ".bin");
}
if (pkgManager === "bun") {
let { stdout } = await execa(pkgManager, ["pm", "bin"]);
return stdout.trim();
}
let { stdout } = await execa(pkgManager, ["bin"]);
return stdout.trim();
};
Expand Down