[bun install] Make it print workspace: instead of workspace://

This commit is contained in:
Jarred Sumner
2023-01-16 18:57:04 -08:00
parent 74b0a1939d
commit 274ae5de1b
3 changed files with 238 additions and 150 deletions

View File

@@ -413,7 +413,7 @@ pub const Version = struct {
return .dist_tag;
},
// link://
// link:
'l' => {
if (isTarball(dependency))
return .tarball;

View File

@@ -189,9 +189,9 @@ pub const Resolution = extern struct {
.remote_tarball => try writer.writeAll(formatter.resolution.value.remote_tarball.slice(formatter.buf)),
.github => try formatter.resolution.value.github.formatAs("github", formatter.buf, layout, opts, writer),
.gitlab => try formatter.resolution.value.gitlab.formatAs("gitlab", formatter.buf, layout, opts, writer),
.workspace => try std.fmt.format(writer, "workspace://{s}", .{formatter.resolution.value.workspace.slice(formatter.buf)}),
.symlink => try std.fmt.format(writer, "link://{s}", .{formatter.resolution.value.symlink.slice(formatter.buf)}),
.single_file_module => try std.fmt.format(writer, "module://{s}", .{formatter.resolution.value.single_file_module.slice(formatter.buf)}),
.workspace => try std.fmt.format(writer, "workspace:{s}", .{formatter.resolution.value.workspace.slice(formatter.buf)}),
.symlink => try std.fmt.format(writer, "link:{s}", .{formatter.resolution.value.symlink.slice(formatter.buf)}),
.single_file_module => try std.fmt.format(writer, "module:{s}", .{formatter.resolution.value.single_file_module.slice(formatter.buf)}),
else => {},
}
}
@@ -211,9 +211,9 @@ pub const Resolution = extern struct {
.remote_tarball => try writer.writeAll(formatter.resolution.value.remote_tarball.slice(formatter.buf)),
.github => try formatter.resolution.value.github.formatAs("github", formatter.buf, layout, opts, writer),
.gitlab => try formatter.resolution.value.gitlab.formatAs("gitlab", formatter.buf, layout, opts, writer),
.workspace => try std.fmt.format(writer, "workspace://{s}", .{formatter.resolution.value.workspace.slice(formatter.buf)}),
.symlink => try std.fmt.format(writer, "link://{s}", .{formatter.resolution.value.symlink.slice(formatter.buf)}),
.single_file_module => try std.fmt.format(writer, "module://{s}", .{formatter.resolution.value.single_file_module.slice(formatter.buf)}),
.workspace => try std.fmt.format(writer, "workspace:{s}", .{formatter.resolution.value.workspace.slice(formatter.buf)}),
.symlink => try std.fmt.format(writer, "link:{s}", .{formatter.resolution.value.symlink.slice(formatter.buf)}),
.single_file_module => try std.fmt.format(writer, "module:{s}", .{formatter.resolution.value.single_file_module.slice(formatter.buf)}),
else => {},
}
}

View File

@@ -1,5 +1,12 @@
import { spawn } from "bun";
import { afterAll, afterEach, beforeAll, beforeEach, expect, it } from "bun:test";
import {
afterAll,
afterEach,
beforeAll,
beforeEach,
expect,
it,
} from "bun:test";
import { bunExe } from "bunExe";
import { mkdir, mkdtemp, readdir, readlink, rm, writeFile } from "fs/promises";
import { join } from "path";
@@ -8,7 +15,7 @@ import { tmpdir } from "os";
let handler, package_dir, requested, server;
function resetHanlder() {
handler = function() {
handler = function () {
return new Response("Tea Break~", { status: 418 });
};
}
@@ -37,16 +44,24 @@ afterEach(async () => {
it("should handle missing package", async () => {
const urls: string[] = [];
handler = async(request) => {
handler = async (request) => {
expect(request.method).toBe("GET");
expect(request.headers.get("accept")).toBe("application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*");
expect(request.headers.get("accept")).toBe(
"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
);
expect(request.headers.get("npm-auth-type")).toBe(null);
expect(await request.text()).toBe("");
urls.push(request.url);
return new Response("bar", { status: 404 });
};
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "foo", "--config", import.meta.dir + "/basic.toml"],
cmd: [
bunExe(),
"install",
"foo",
"--config",
import.meta.dir + "/basic.toml",
],
cwd: package_dir,
stdout: null,
stdin: "pipe",
@@ -58,7 +73,9 @@ it("should handle missing package", async () => {
});
expect(stderr).toBeDefined();
const err = await new Response(stderr).text();
expect(err.split(/\r?\n/)).toContain('error: package "foo" not found localhost/foo 404');
expect(err.split(/\r?\n/)).toContain(
'error: package "foo" not found localhost/foo 404',
);
expect(stdout).toBeDefined();
expect(await new Response(stdout).text()).toBe("");
expect(urls).toContain("http://localhost:54321/foo");
@@ -70,9 +87,11 @@ it("should handle @scoped authentication", async () => {
let seen_token = false;
const url = "http://localhost:54321/@foo/bar";
const urls: string[] = [];
handler = async(request) => {
handler = async (request) => {
expect(request.method).toBe("GET");
expect(request.headers.get("accept")).toBe("application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*");
expect(request.headers.get("accept")).toBe(
"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
);
if (request.url === url) {
expect(request.headers.get("authorization")).toBe("Bearer bar");
expect(request.headers.get("npm-auth-type")).toBe("legacy");
@@ -85,7 +104,13 @@ it("should handle @scoped authentication", async () => {
return new Response("Feeling lucky?", { status: 555 });
};
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "@foo/bar", "--config", import.meta.dir + "/basic.toml"],
cmd: [
bunExe(),
"install",
"@foo/bar",
"--config",
import.meta.dir + "/basic.toml",
],
cwd: package_dir,
stdout: null,
stdin: "pipe",
@@ -107,18 +132,22 @@ it("should handle @scoped authentication", async () => {
});
it("should handle workspaces", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: [
"bar",
],
}));
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: ["bar"],
}),
);
await mkdir(join(package_dir, "bar"));
await writeFile(join(package_dir, "bar", "package.json"), JSON.stringify({
name: "Bar",
version: "0.0.2",
}));
await writeFile(
join(package_dir, "bar", "package.json"),
JSON.stringify({
name: "Bar",
version: "0.0.2",
}),
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -136,41 +165,49 @@ it("should handle workspaces", async () => {
expect(stdout).toBeDefined();
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
" + Bar@workspace://bar",
" + Bar@workspace:bar",
"",
" 1 packages installed",
]);
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Bar"]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(join("..", "bar"));
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(
join("..", "bar"),
);
});
it("should handle inter-dependency between workspaces", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: [
"bar",
"packages/baz",
],
}));
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: ["bar", "packages/baz"],
}),
);
await mkdir(join(package_dir, "bar"));
await writeFile(join(package_dir, "bar", "package.json"), JSON.stringify({
name: "Bar",
version: "0.0.2",
dependencies: {
"Baz": "0.0.3",
},
}));
await writeFile(
join(package_dir, "bar", "package.json"),
JSON.stringify({
name: "Bar",
version: "0.0.2",
dependencies: {
Baz: "0.0.3",
},
}),
);
await mkdir(join(package_dir, "packages", "baz"), { recursive: true });
await writeFile(join(package_dir, "packages", "baz", "package.json"), JSON.stringify({
name: "Baz",
version: "0.0.3",
dependencies: {
"Bar": "0.0.2",
},
}));
await writeFile(
join(package_dir, "packages", "baz", "package.json"),
JSON.stringify({
name: "Baz",
version: "0.0.3",
dependencies: {
Bar: "0.0.2",
},
}),
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -188,43 +225,56 @@ it("should handle inter-dependency between workspaces", async () => {
expect(stdout).toBeDefined();
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
" + Bar@workspace://bar",
" + Baz@workspace://packages/baz",
" + Bar@workspace:bar",
" + Baz@workspace:packages/baz",
"",
" 2 packages installed",
]);
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Bar", "Baz"]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(join("..", "bar"));
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(join("..", "packages", "baz"));
expect(await readdir(join(package_dir, "node_modules"))).toEqual([
"Bar",
"Baz",
]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(
join("..", "bar"),
);
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(
join("..", "packages", "baz"),
);
});
it("should handle inter-dependency between workspaces (devDependencies)", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: [
"bar",
"packages/baz",
],
}));
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: ["bar", "packages/baz"],
}),
);
await mkdir(join(package_dir, "bar"));
await writeFile(join(package_dir, "bar", "package.json"), JSON.stringify({
name: "Bar",
version: "0.0.2",
devDependencies: {
"Baz": "0.0.3",
},
}));
await writeFile(
join(package_dir, "bar", "package.json"),
JSON.stringify({
name: "Bar",
version: "0.0.2",
devDependencies: {
Baz: "0.0.3",
},
}),
);
await mkdir(join(package_dir, "packages", "baz"), { recursive: true });
await writeFile(join(package_dir, "packages", "baz", "package.json"), JSON.stringify({
name: "Baz",
version: "0.0.3",
devDependencies: {
"Bar": "0.0.2",
},
}));
await writeFile(
join(package_dir, "packages", "baz", "package.json"),
JSON.stringify({
name: "Baz",
version: "0.0.3",
devDependencies: {
Bar: "0.0.2",
},
}),
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -242,43 +292,56 @@ it("should handle inter-dependency between workspaces (devDependencies)", async
expect(stdout).toBeDefined();
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
" + Bar@workspace://bar",
" + Baz@workspace://packages/baz",
" + Bar@workspace:bar",
" + Baz@workspace:packages/baz",
"",
" 2 packages installed",
]);
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Bar", "Baz"]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(join("..", "bar"));
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(join("..", "packages", "baz"));
expect(await readdir(join(package_dir, "node_modules"))).toEqual([
"Bar",
"Baz",
]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(
join("..", "bar"),
);
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(
join("..", "packages", "baz"),
);
});
it("should handle inter-dependency between workspaces (optionalDependencies)", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: [
"bar",
"packages/baz",
],
}));
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: ["bar", "packages/baz"],
}),
);
await mkdir(join(package_dir, "bar"));
await writeFile(join(package_dir, "bar", "package.json"), JSON.stringify({
name: "Bar",
version: "0.0.2",
optionalDependencies: {
"Baz": "0.0.3",
},
}));
await writeFile(
join(package_dir, "bar", "package.json"),
JSON.stringify({
name: "Bar",
version: "0.0.2",
optionalDependencies: {
Baz: "0.0.3",
},
}),
);
await mkdir(join(package_dir, "packages", "baz"), { recursive: true });
await writeFile(join(package_dir, "packages", "baz", "package.json"), JSON.stringify({
name: "Baz",
version: "0.0.3",
optionalDependencies: {
"Bar": "0.0.2",
},
}));
await writeFile(
join(package_dir, "packages", "baz", "package.json"),
JSON.stringify({
name: "Baz",
version: "0.0.3",
optionalDependencies: {
Bar: "0.0.2",
},
}),
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -296,37 +359,48 @@ it("should handle inter-dependency between workspaces (optionalDependencies)", a
expect(stdout).toBeDefined();
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
" + Bar@workspace://bar",
" + Baz@workspace://packages/baz",
" + Bar@workspace:bar",
" + Baz@workspace:packages/baz",
"",
" 2 packages installed",
]);
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Bar", "Baz"]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(join("..", "bar"));
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(join("..", "packages", "baz"));
expect(await readdir(join(package_dir, "node_modules"))).toEqual([
"Bar",
"Baz",
]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(
join("..", "bar"),
);
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(
join("..", "packages", "baz"),
);
});
it("should ignore peerDependencies within workspaces", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: [
"packages/baz",
],
peerDependencies: {
"Bar": ">=0.0.2",
},
}));
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
workspaces: ["packages/baz"],
peerDependencies: {
Bar: ">=0.0.2",
},
}),
);
await mkdir(join(package_dir, "packages", "baz"), { recursive: true });
await writeFile(join(package_dir, "packages", "baz", "package.json"), JSON.stringify({
name: "Baz",
version: "0.0.3",
peerDependencies: {
"Moo": ">=0.0.4",
},
}));
await writeFile(
join(package_dir, "packages", "baz", "package.json"),
JSON.stringify({
name: "Baz",
version: "0.0.3",
peerDependencies: {
Moo: ">=0.0.4",
},
}),
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -344,37 +418,49 @@ it("should ignore peerDependencies within workspaces", async () => {
expect(stdout).toBeDefined();
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
" + Baz@workspace://packages/baz",
" + Baz@workspace:packages/baz",
"",
" 1 packages installed",
]);
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Baz"]);
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(join("..", "packages", "baz"));
expect(await readlink(join(package_dir, "node_modules", "Baz"))).toBe(
join("..", "packages", "baz"),
);
});
it("should handle life-cycle scripts within workspaces", async () => {
await writeFile(join(package_dir, "package.json"), JSON.stringify({
name: "Foo",
version: "0.0.1",
scripts: {
install: [bunExe(), "index.js"].join(" "),
},
workspaces: [
"bar",
],
}));
await writeFile(join(package_dir, "index.js"), 'console.log("[scripts:run] Foo");');
await writeFile(
join(package_dir, "package.json"),
JSON.stringify({
name: "Foo",
version: "0.0.1",
scripts: {
install: [bunExe(), "index.js"].join(" "),
},
workspaces: ["bar"],
}),
);
await writeFile(
join(package_dir, "index.js"),
'console.log("[scripts:run] Foo");',
);
await mkdir(join(package_dir, "bar"));
await writeFile(join(package_dir, "bar", "package.json"), JSON.stringify({
name: "Bar",
version: "0.0.2",
scripts: {
preinstall: [bunExe(), "index.js"].join(" "),
},
}));
await writeFile(join(package_dir, "bar", "index.js"), 'console.log("[scripts:run] Bar");');
await writeFile(
join(package_dir, "bar", "package.json"),
JSON.stringify({
name: "Bar",
version: "0.0.2",
scripts: {
preinstall: [bunExe(), "index.js"].join(" "),
},
}),
);
await writeFile(
join(package_dir, "bar", "index.js"),
'console.log("[scripts:run] Bar");',
);
const { stdout, stderr, exited } = spawn({
cmd: [bunExe(), "install", "--config", import.meta.dir + "/basic.toml"],
cwd: package_dir,
@@ -393,7 +479,7 @@ it("should handle life-cycle scripts within workspaces", async () => {
const out = await new Response(stdout).text();
expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([
"[scripts:run] Bar",
" + Bar@workspace://bar",
" + Bar@workspace:bar",
"[scripts:run] Foo",
"",
" 1 packages installed",
@@ -401,5 +487,7 @@ it("should handle life-cycle scripts within workspaces", async () => {
expect(await exited).toBe(0);
expect(requested).toBe(0);
expect(await readdir(join(package_dir, "node_modules"))).toEqual(["Bar"]);
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(join("..", "bar"));
expect(await readlink(join(package_dir, "node_modules", "Bar"))).toBe(
join("..", "bar"),
);
});