This commit is contained in:
Dylan Conway
2025-10-27 19:44:16 -07:00
parent 29cd7e9c68
commit 5d8fe74eb8
2 changed files with 89 additions and 67 deletions

View File

@@ -1154,73 +1154,6 @@ pub fn Package(comptime SemverIntType: type) type {
}
dependency_version.value.workspace = path;
} else if (workspace_range == null) {
const workspace = dependency_version.value.workspace.slice(buf);
const path = string_builder.append(String, if (strings.eqlComptime(workspace, "*")) "*" else brk: {
var buf2: bun.PathBuffer = undefined;
const rel = Path.relativePlatform(
FileSystem.instance.top_level_dir,
Path.joinAbsStringBuf(
FileSystem.instance.top_level_dir,
&buf2,
&[_]string{
source.path.name.dir,
workspace,
},
.auto,
),
.auto,
false,
);
if (rel.len == 0) {
break :brk ".";
}
if (comptime Environment.isWindows) {
bun.path.dangerouslyConvertPathToPosixInPlace(u8, Path.relative_to_common_path_buf[0..rel.len]);
}
break :brk rel;
});
if (path.len() != 1 or path.inlineSlice()[0] != '.') {
if (comptime Environment.allow_assert) {
assert(!std.fs.path.isAbsolute(path.slice(buf)));
}
dependency_version.value.workspace = path;
const workspace_entry = try lockfile.workspace_paths.getOrPut(allocator, name_hash);
const found_matching_workspace = workspace_entry.found_existing;
if (workspace_version) |ver| {
try lockfile.workspace_versions.put(allocator, name_hash, ver);
for (package_dependencies[0..dependencies_count]) |*package_dep| {
if (switch (package_dep.version.tag) {
// `dependencies` & `workspaces` defined within the same `package.json`
.npm => String.Builder.stringHash(package_dep.realname().slice(buf)) == name_hash and
package_dep.version.value.npm.version.satisfies(ver, buf, buf),
// `workspace:*`
.workspace => found_matching_workspace and
String.Builder.stringHash(package_dep.realname().slice(buf)) == name_hash,
else => false,
}) {
package_dep.version = dependency_version;
workspace_entry.value_ptr.* = path;
return null;
}
}
} else if (workspace_entry.found_existing) {
for (package_dependencies[0..dependencies_count]) |*package_dep| {
if (package_dep.version.tag == .workspace and
String.Builder.stringHash(package_dep.realname().slice(buf)) == name_hash)
{
package_dep.version = dependency_version;
return null;
}
}
return error.InstallFailed;
}
workspace_entry.value_ptr.* = path;
}
}
},
else => {},

View File

@@ -248,6 +248,95 @@ test("successfully installs workspace when path already exists in node_modules",
});
});
describe("root dependencies in workspace", () => {
const basicTests = ["workspace:*", "workspace:1.0.0", "workspace:../../"];
for (const basicTest of basicTests) {
test(`works with "${basicTest}"`, async () => {
const { packageDir } = await verdaccio.createTestDir({
bunfigOpts: { isolated: true },
files: {
"package.json": JSON.stringify({
name: "root",
version: "1.0.0",
workspaces: ["packages/*"],
}),
"packages/pkg1/package.json": JSON.stringify({
name: "pkg1",
dependencies: {
root: basicTest,
},
}),
},
});
await runBunInstall(env, packageDir);
expect(await file(join(packageDir, "packages", "pkg1", "node_modules", "root", "package.json")).json()).toEqual({
name: "root",
version: "1.0.0",
workspaces: ["packages/*"],
});
// another install succeeds
await rm(join(packageDir, "packages", "pkg1", "node_modules", "root"));
await runBunInstall(env, packageDir, { savesLockfile: false });
expect(await file(join(packageDir, "packages", "pkg1", "node_modules", "root", "package.json")).json()).toEqual({
name: "root",
version: "1.0.0",
workspaces: ["packages/*"],
});
});
}
test("multiple dependencies on root package", async () => {
const { packageDir } = await verdaccio.createTestDir({
bunfigOpts: { isolated: true },
files: {
"package.json": JSON.stringify({
name: "root",
version: "1.0.0",
workspaces: ["packages/*"],
dependencies: {
root: "workspace:1.0.0",
},
}),
"packages/pkg1/package.json": JSON.stringify({
name: "pkg1",
dependencies: {
root: "workspace:*",
},
}),
"packages/pkg2/package.json": JSON.stringify({
name: "pkg2",
dependencies: {
root: "workspace:../../",
},
}),
},
});
await runBunInstall(env, packageDir);
(
await Promise.all([
file(join(packageDir, "packages/pkg1/node_modules/root/package.json")).json(),
file(join(packageDir, "packages/pkg2/node_modules/root/package.json")).json(),
file(join(packageDir, "node_modules/root/package.json")).json(),
])
).map(rootJson => {
expect(rootJson).toEqual({
name: "root",
version: "1.0.0",
workspaces: ["packages/*"],
dependencies: {
root: "workspace:1.0.0",
},
});
});
});
});
test("adding workspace in workspace edits package.json with correct version (workspace:*)", async () => {
await Promise.all([
write(