mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
## Summary - Fixed `bun install --frozen-lockfile` to use scope-specific registry for scoped packages when the lockfile has an empty registry URL When parsing a `bun.lock` file with an empty registry URL for a scoped package (like `@example/test-package`), bun was unconditionally using the default npm registry (`https://registry.npmjs.org/`) instead of looking up the scope-specific registry from `bunfig.toml`. For example, with this configuration in `bunfig.toml`: ```toml [install.scopes] example = { url = "https://npm.pkg.github.com" } ``` And this lockfile entry with an empty registry URL: ```json "@example/test-package": ["@example/test-package@1.0.0", "", {}, "sha512-AAAA"] ``` bun would try to fetch from `https://registry.npmjs.org/@example/test-package/-/...` instead of `https://npm.pkg.github.com/@example/test-package/-/...`. The fix uses `manager.scopeForPackageName()` (the same pattern used in `pnpm.zig`) to look up the correct scope-specific registry URL. ## Test plan - [x] Added regression test `test/regression/issue/026039.test.ts` that verifies: - Scoped packages use the scope-specific registry from `bunfig.toml` - Non-scoped packages continue to use the default registry - [x] Verified test fails with system bun (without fix) and passes with debug build (with fix) Fixes #26039 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
106 lines
3.5 KiB
TypeScript
106 lines
3.5 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
|
|
|
// Test for https://github.com/oven-sh/bun/issues/26039
|
|
// When parsing a bun.lock file with an empty registry URL for a scoped package,
|
|
// bun should use the scope-specific registry from bunfig.toml, not the default npm registry.
|
|
test("frozen lockfile should use scope-specific registry for scoped packages", async () => {
|
|
const dir = tempDirWithFiles("scoped-registry-test", {
|
|
"package.json": JSON.stringify({
|
|
name: "test-scoped-registry",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"@example/test-package": "^1.0.0",
|
|
},
|
|
}),
|
|
"bunfig.toml": `
|
|
[install.scopes]
|
|
example = { url = "https://npm.pkg.github.com" }
|
|
`,
|
|
// bun.lock with empty string for registry URL - this should trigger the scope lookup
|
|
"bun.lock": JSON.stringify(
|
|
{
|
|
lockfileVersion: 1,
|
|
workspaces: {
|
|
"": {
|
|
dependencies: {
|
|
"@example/test-package": "^1.0.0",
|
|
},
|
|
},
|
|
},
|
|
packages: {
|
|
"@example/test-package": ["@example/test-package@1.0.0", "", {}, "sha512-AAAA"],
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
});
|
|
|
|
// Run bun install --frozen-lockfile. It will fail because the package doesn't exist,
|
|
// but the error message should show the correct registry URL (npm.pkg.github.com, not registry.npmjs.org)
|
|
const { stderr, exitCode } = Bun.spawnSync({
|
|
cmd: [bunExe(), "install", "--frozen-lockfile"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
});
|
|
|
|
const stderrText = stderr.toString();
|
|
|
|
// Before the fix, this would try to fetch from https://registry.npmjs.org/@example/test-package/-/test-package-1.0.0.tgz
|
|
// After the fix, it should try to fetch from https://npm.pkg.github.com/@example/test-package/-/test-package-1.0.0.tgz
|
|
expect(stderrText).toContain("npm.pkg.github.com");
|
|
expect(stderrText).not.toContain("registry.npmjs.org");
|
|
// The install should fail because the package doesn't exist on the registry
|
|
expect(exitCode).not.toBe(0);
|
|
});
|
|
|
|
// Test that non-scoped packages still use the default registry when registry URL is empty
|
|
test("frozen lockfile should use default registry for non-scoped packages", async () => {
|
|
const dir = tempDirWithFiles("non-scoped-registry-test", {
|
|
"package.json": JSON.stringify({
|
|
name: "test-non-scoped-registry",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"fake-nonexistent-package": "^1.0.0",
|
|
},
|
|
}),
|
|
"bunfig.toml": `
|
|
[install.scopes]
|
|
example = { url = "https://npm.pkg.github.com" }
|
|
`,
|
|
// bun.lock with empty string for registry URL for non-scoped package
|
|
"bun.lock": JSON.stringify(
|
|
{
|
|
lockfileVersion: 1,
|
|
workspaces: {
|
|
"": {
|
|
dependencies: {
|
|
"fake-nonexistent-package": "^1.0.0",
|
|
},
|
|
},
|
|
},
|
|
packages: {
|
|
"fake-nonexistent-package": ["fake-nonexistent-package@1.0.0", "", {}, "sha512-BBBB"],
|
|
},
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
});
|
|
|
|
const { stderr, exitCode } = Bun.spawnSync({
|
|
cmd: [bunExe(), "install", "--frozen-lockfile"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
});
|
|
|
|
const stderrText = stderr.toString();
|
|
|
|
// Non-scoped packages should still use the default registry
|
|
expect(stderrText).toContain("registry.npmjs.org");
|
|
expect(stderrText).not.toContain("npm.pkg.github.com");
|
|
// The install should fail because the package doesn't exist on the registry
|
|
expect(exitCode).not.toBe(0);
|
|
});
|