Skip to content

Commit 54008c6

Browse files
committed
feat(npm-dist-tag): Use fetch API instead of CLI to make changes
1 parent b387881 commit 54008c6

File tree

8 files changed

+222
-151
lines changed

8 files changed

+222
-151
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"use strict";
22

33
const mockAdd = jest.fn(() => Promise.resolve());
4-
const mockCheck = jest.fn(() => true);
4+
const mockList = jest.fn(() => Promise.resolve({}));
55
const mockRemove = jest.fn(() => Promise.resolve());
66

77
exports.add = mockAdd;
8-
exports.check = mockCheck;
8+
exports.list = mockList;
99
exports.remove = mockRemove;

commands/publish/__tests__/publish-command.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ Set {
108108
"package-2",
109109
// package-5 is private
110110
]);
111-
expect(npmDistTag.check).not.toHaveBeenCalled();
112111
expect(npmDistTag.remove).not.toHaveBeenCalled();
113112
expect(npmDistTag.add).not.toHaveBeenCalled();
114113

commands/publish/__tests__/publish-tagging.test.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ test("publish --npm-tag", async () => {
2929
await lernaPublish(cwd)("--npm-tag", "custom");
3030

3131
expect(npmPublish.registry.get("package-3")).toBe("custom");
32-
expect(npmDistTag.check).not.toHaveBeenCalled();
32+
expect(npmDistTag.remove).not.toHaveBeenCalled();
3333
});
3434

3535
test("publish --temp-tag", async () => {
@@ -41,14 +41,15 @@ test("publish --temp-tag", async () => {
4141

4242
expect(npmPublish.registry.get("package-4")).toBe("lerna-temp");
4343

44-
expect(npmDistTag.remove).toHaveBeenLastCalledWith(
45-
expect.objectContaining({ name: "package-4" }),
46-
"lerna-temp",
47-
expect.objectContaining({ registry: "test-registry" })
48-
);
49-
expect(npmDistTag.add).toHaveBeenLastCalledWith(
50-
expect.objectContaining({ name: "package-4", version: "1.0.1" }),
51-
"latest",
52-
expect.objectContaining({ registry: "test-registry" })
53-
);
44+
const conf = expect.objectContaining({
45+
sources: expect.objectContaining({
46+
cli: {
47+
data: expect.objectContaining({
48+
registry: "test-registry",
49+
}),
50+
},
51+
}),
52+
});
53+
expect(npmDistTag.remove).toHaveBeenLastCalledWith("package-4@1.0.1", "lerna-temp", conf);
54+
expect(npmDistTag.add).toHaveBeenLastCalledWith("package-4@1.0.1", "latest", conf);
5455
});

commands/publish/index.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -576,16 +576,14 @@ class PublishCommand extends Command {
576576
let chain = Promise.resolve();
577577

578578
const actions = [
579-
pkg =>
580-
Promise.resolve()
581-
.then(() => npmDistTag.check(pkg, "lerna-temp", this.npmConfig))
582-
.then(exists => {
583-
if (exists) {
584-
return npmDistTag.remove(pkg, "lerna-temp", this.npmConfig);
585-
}
586-
})
587-
.then(() => npmDistTag.add(pkg, distTag, this.npmConfig))
588-
.then(() => pkg),
579+
pkg => {
580+
const spec = `${pkg.name}@${pkg.version}`;
581+
582+
return Promise.resolve()
583+
.then(() => npmDistTag.remove(spec, "lerna-temp", this.conf))
584+
.then(() => npmDistTag.add(spec, distTag, this.conf))
585+
.then(() => pkg);
586+
},
589587
pkg => {
590588
tracker.info("dist-tag", "%s@%s => %j", pkg.name, pkg.version, distTag);
591589
tracker.completeWork(1);

package-lock.json

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 114 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,138 @@
11
"use strict";
22

3-
jest.mock("@lerna/child-process");
4-
5-
const os = require("os");
3+
jest.mock("libnpm/fetch");
64

75
// mocked modules
8-
const ChildProcessUtilities = require("@lerna/child-process");
6+
const fetch = require("libnpm/fetch");
97

108
// file under test
119
const npmDistTag = require("..");
1210

13-
describe("dist-tag", () => {
14-
ChildProcessUtilities.exec.mockResolvedValue();
15-
16-
describe("npmDistTag.add()", () => {
17-
const pkg = {
18-
name: "foo-pkg",
19-
version: "1.0.0",
20-
location: "/test/npm/dist-tag/add",
21-
};
22-
const tag = "added-tag";
23-
const registry = "https://custom-registry/add";
24-
25-
it("adds a dist-tag for a given package@version", async () => {
26-
await npmDistTag.add(pkg, tag, {});
27-
28-
expect(ChildProcessUtilities.exec).toHaveBeenLastCalledWith(
29-
"npm",
30-
["dist-tag", "add", "foo-pkg@1.0.0", tag],
31-
{
32-
cwd: pkg.location,
33-
env: {},
34-
pkg,
35-
}
36-
);
37-
});
11+
const stubLog = {
12+
verbose: jest.fn(),
13+
info: jest.fn(),
14+
warn: jest.fn(),
15+
};
16+
const baseOptions = new Map([["log", stubLog], ["tag", "latest"]]);
17+
18+
fetch.mockImplementation(() => Promise.resolve());
19+
fetch.json.mockImplementation(() => Promise.resolve({}));
20+
21+
describe("npmDistTag.add()", () => {
22+
it("adds a dist-tag for a given package@version", async () => {
23+
const opts = new Map(baseOptions);
24+
const tags = await npmDistTag.add("@scope/some-pkg@1.0.1", "added-tag", opts);
3825

39-
it("supports custom registry", async () => {
40-
await npmDistTag.add(pkg, tag, { registry });
41-
42-
expect(ChildProcessUtilities.exec).toHaveBeenLastCalledWith(
43-
"npm",
44-
["dist-tag", "add", "foo-pkg@1.0.0", tag],
45-
{
46-
cwd: pkg.location,
47-
env: {
48-
npm_config_registry: registry,
49-
},
50-
pkg,
51-
}
52-
);
26+
expect(tags).toEqual({
27+
"added-tag": "1.0.1",
5328
});
29+
expect(fetch).toHaveBeenLastCalledWith(
30+
"-/package/@scope%2fsome-pkg/dist-tags/added-tag",
31+
expect.objectContaining({
32+
method: "PUT",
33+
body: JSON.stringify("1.0.1"),
34+
headers: {
35+
"content-type": "application/json",
36+
},
37+
})
38+
);
5439
});
5540

56-
describe("npmDistTag.remove()", () => {
57-
const pkg = {
58-
name: "bar-pkg",
59-
location: "/test/npm/dist-tag/remove",
60-
};
61-
const tag = "removed-tag";
62-
const registry = "https://custom-registry/remove";
63-
64-
it("removes a dist-tag for a given package", async () => {
65-
await npmDistTag.remove(pkg, tag, {});
66-
67-
expect(ChildProcessUtilities.exec).toHaveBeenLastCalledWith("npm", ["dist-tag", "rm", pkg.name, tag], {
68-
cwd: pkg.location,
69-
env: {},
70-
pkg,
71-
});
72-
});
41+
it("does not attempt to add duplicate of existing tag", async () => {
42+
fetch.json.mockImplementationOnce(() =>
43+
Promise.resolve({
44+
latest: "1.0.0",
45+
"dupe-tag": "1.0.1",
46+
})
47+
);
7348

74-
it("supports custom registry", async () => {
75-
await npmDistTag.remove(pkg, tag, { registry });
49+
const opts = new Map(baseOptions);
50+
const tags = await npmDistTag.add("@scope/some-pkg@1.0.1", "dupe-tag", opts);
7651

77-
expect(ChildProcessUtilities.exec).toHaveBeenLastCalledWith("npm", ["dist-tag", "rm", pkg.name, tag], {
78-
cwd: pkg.location,
79-
env: {
80-
npm_config_registry: registry,
81-
},
82-
pkg,
83-
});
52+
expect(tags).toEqual({
53+
latest: "1.0.0",
54+
"dupe-tag": "1.0.1",
8455
});
56+
expect(fetch).not.toHaveBeenCalled();
57+
expect(stubLog.warn).toHaveBeenLastCalledWith(
58+
"dist-tag",
59+
"@scope/some-pkg@dupe-tag already set to 1.0.1"
60+
);
8561
});
8662

87-
describe("npmDistTag.check()", () => {
88-
const pkg = {
89-
name: "baz-pkg",
90-
location: "/test/npm/dist-tag/check",
91-
};
92-
const registry = "https://custom-registry/check";
93-
94-
it("tests if a dist-tag for a given package exists", () => {
95-
ChildProcessUtilities.execSync.mockReturnValue(["latest", "target-tag"].join(os.EOL));
96-
97-
expect(npmDistTag.check(pkg, "target-tag", {})).toBe(true);
98-
expect(npmDistTag.check(pkg, "latest", {})).toBe(true);
99-
expect(npmDistTag.check(pkg, "missing", {})).toBe(false);
100-
101-
expect(ChildProcessUtilities.execSync).toHaveBeenLastCalledWith("npm", ["dist-tag", "ls", pkg.name], {
102-
cwd: pkg.location,
103-
env: {},
104-
pkg,
105-
});
63+
it("defaults tag argument to opts.tag", async () => {
64+
fetch.json.mockImplementationOnce(() =>
65+
Promise.resolve({
66+
latest: "1.0.0",
67+
})
68+
);
69+
70+
const opts = new Map(baseOptions);
71+
const tags = await npmDistTag.add("@scope/some-pkg@1.0.1", undefined, opts);
72+
73+
expect(tags).toEqual({
74+
latest: "1.0.1",
10675
});
76+
});
77+
});
78+
79+
describe("npmDistTag.remove()", () => {
80+
it("removes an existing dist-tag for a given package", async () => {
81+
fetch.json.mockImplementationOnce(() =>
82+
Promise.resolve({
83+
latest: "1.0.0",
84+
"removed-tag": "1.0.1",
85+
})
86+
);
87+
88+
const opts = new Map(baseOptions);
89+
const tags = await npmDistTag.remove("@scope/some-pkg@1.0.1", "removed-tag", opts);
90+
91+
expect(tags).not.toHaveProperty("removed-tag");
92+
expect(fetch).toHaveBeenLastCalledWith(
93+
"-/package/@scope%2fsome-pkg/dist-tags/removed-tag",
94+
expect.objectContaining({
95+
method: "DELETE",
96+
})
97+
);
98+
});
10799

108-
it("supports custom registry", () => {
109-
ChildProcessUtilities.execSync.mockReturnValue("target-tag");
100+
it("does not attempt removal of nonexistent tag", async () => {
101+
const opts = new Map(baseOptions);
102+
const tags = await npmDistTag.remove("@scope/some-pkg@1.0.1", "missing-tag", opts);
110103

111-
expect(npmDistTag.check(pkg, "target-tag", { registry })).toBe(true);
104+
expect(tags).toEqual({});
105+
expect(fetch).not.toHaveBeenCalled();
106+
expect(stubLog.info).toHaveBeenLastCalledWith(
107+
"dist-tag",
108+
'"missing-tag" is not a dist-tag on @scope/some-pkg'
109+
);
110+
});
111+
});
112112

113-
expect(ChildProcessUtilities.execSync).toHaveBeenLastCalledWith("npm", ["dist-tag", "ls", pkg.name], {
114-
cwd: pkg.location,
115-
env: {
116-
npm_config_registry: registry,
117-
},
118-
pkg,
119-
});
113+
describe("npmDistTag.list()", () => {
114+
it("returns dictionary of dist-tags", async () => {
115+
fetch.json.mockImplementationOnce(() =>
116+
Promise.resolve({
117+
latest: "1.0.0",
118+
"other-tag": "1.0.1",
119+
})
120+
);
121+
122+
const opts = new Map(baseOptions);
123+
const tags = await npmDistTag.list("@scope/some-pkg", opts);
124+
125+
expect(tags).toEqual({
126+
latest: "1.0.0",
127+
"other-tag": "1.0.1",
120128
});
129+
expect(fetch.json).toHaveBeenLastCalledWith(
130+
"-/package/@scope%2fsome-pkg/dist-tags",
131+
expect.objectContaining({
132+
spec: expect.objectContaining({
133+
name: "@scope/some-pkg",
134+
}),
135+
})
136+
);
121137
});
122138
});

0 commit comments

Comments
 (0)