Skip to content

Commit

Permalink
refactor(publish): introduce figgy-pudding to share fetch opts
Browse files Browse the repository at this point in the history
  • Loading branch information
evocateur committed Dec 19, 2018
1 parent 111053b commit 405b094
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 40 deletions.
15 changes: 6 additions & 9 deletions commands/publish/__tests__/publish-command.test.js
Expand Up @@ -32,6 +32,8 @@ const initFixture = require("@lerna-test/init-fixture")(__dirname);
// file under test
const lernaPublish = require("@lerna-test/command-runner")(require("../command"));

expect.extend(require("@lerna-test/figgy-pudding-matchers"));

describe("PublishCommand", () => {
describe("cli validation", () => {
let cwd;
Expand Down Expand Up @@ -116,15 +118,10 @@ Set {
expect(getNpmUsername.registry.get(testDir).get("registry")).toBe("https://registry.npmjs.org/");

expect(verifyNpmPackageAccess).toHaveBeenCalled();
expect(verifyNpmPackageAccess.registry.get(testDir)).toMatchInlineSnapshot(`
Set {
"package-1",
"package-2",
"package-3",
"package-4",
"username: lerna-test",
}
`);
expect(verifyNpmPackageAccess).toHaveBeenLastCalledWith(
expect.any(Array),
expect.figgyPudding({ registry: "https://registry.npmjs.org/" })
);
});

it("publishes changed independent packages", async () => {
Expand Down
4 changes: 3 additions & 1 deletion commands/publish/__tests__/verify-npm-package-access.test.js
Expand Up @@ -15,6 +15,8 @@ access.lsPackages.mockImplementation(() =>
})
);

expect.extend(require("@lerna-test/figgy-pudding-matchers"));

describe("verifyNpmPackageAccess", () => {
const origConsoleError = console.error;

Expand All @@ -40,7 +42,7 @@ describe("verifyNpmPackageAccess", () => {

expect(access.lsPackages).toHaveBeenLastCalledWith(
"lerna-test",
expect.objectContaining({
expect.figgyPudding({
username: "lerna-test",
registry: "https://registry.npmjs.org/",
"fetch-retries": 0,
Expand Down
2 changes: 1 addition & 1 deletion commands/publish/index.js
Expand Up @@ -402,7 +402,7 @@ class PublishCommand extends Command {

// if no username was retrieved, don't bother validating
if (this.conf.get("username") && this.verifyAccess) {
chain = chain.then(() => verifyNpmPackageAccess(this.packagesToPublish, this.conf));
chain = chain.then(() => verifyNpmPackageAccess(this.packagesToPublish, this.conf.snapshot));
}

return chain;
Expand Down
18 changes: 1 addition & 17 deletions commands/publish/lib/__mocks__/verify-npm-package-access.js
@@ -1,22 +1,6 @@
"use strict";

const registry = new Map();

// to mock user modules, you _must_ call `jest.mock('./path/to/module')`
const mockVerifyNpmPackageAccess = jest.fn((packages, opts) => {
const result = new Set(packages.map(pkg => pkg.name));

result.add(`username: ${opts.get("username")}`);

registry.set(opts.prefix, result);

return Promise.resolve();
});

// keep test data isolated
afterEach(() => {
registry.clear();
});
const mockVerifyNpmPackageAccess = jest.fn(() => Promise.resolve());

module.exports = mockVerifyNpmPackageAccess;
module.exports.registry = registry;
20 changes: 20 additions & 0 deletions commands/publish/lib/fetch-config.js
@@ -0,0 +1,20 @@
"use strict";

const log = require("libnpm/log");
const figgyPudding = require("figgy-pudding");

module.exports = figgyPudding(
{
"fetch-retries": {},
fetchRetries: "fetch-retries",
log: { default: log },
registry: {},
username: {},
},
{
other() {
// open it up for the sake of tests
return true;
},
}
);
22 changes: 10 additions & 12 deletions commands/publish/lib/verify-npm-package-access.js
@@ -1,28 +1,26 @@
"use strict";

const log = require("libnpm/log");
const access = require("libnpm/access");
const RegistryConfig = require("npm-registry-fetch/config");
const ValidationError = require("@lerna/validation-error");
const FetchConfig = require("./fetch-config");

module.exports = verifyNpmPackageAccess;

function verifyNpmPackageAccess(packages, opts) {
log.silly("verifyNpmPackageAccess");

// eslint-disable-next-line no-param-reassign
opts = RegistryConfig(opts, {
function verifyNpmPackageAccess(packages, _opts) {
const opts = FetchConfig(_opts, {
// don't wait forever for third-party failures to be dealt with
"fetch-retries": 0,
});

return access.lsPackages(opts.username, opts.toJSON()).then(success, failure);
opts.log.silly("verifyNpmPackageAccess");

return access.lsPackages(opts.username, opts).then(success, failure);

function success(result) {
// when _no_ results received, access.lsPackages returns null
// we can only assume that the packages in question have never been published
if (result === null) {
log.warn(
opts.log.warn(
"",
"The logged-in user does not have any previously-published packages, skipping permission checks..."
);
Expand All @@ -42,7 +40,7 @@ function verifyNpmPackageAccess(packages, opts) {
// pass if registry does not support ls-packages endpoint
if (err.code === "E500" || err.code === "E404") {
// most likely a private registry (npm Enterprise, verdaccio, etc)
log.warn(
opts.log.warn(
"EREGISTRY",
"Registry %j does not support `npm access ls-packages`, skipping permission checks...",
// registry
Expand All @@ -54,9 +52,9 @@ function verifyNpmPackageAccess(packages, opts) {
}

// Log the error cleanly to stderr
log.pause();
opts.log.pause();
console.error(err.message); // eslint-disable-line no-console
log.resume();
opts.log.resume();

throw new ValidationError("EWHOAMI", "Authentication error. Use `npm whoami` to troubleshoot.");
}
Expand Down
1 change: 1 addition & 0 deletions commands/publish/package.json
Expand Up @@ -50,6 +50,7 @@
"@lerna/run-parallel-batches": "file:../../utils/run-parallel-batches",
"@lerna/validation-error": "file:../../core/validation-error",
"@lerna/version": "file:../version",
"figgy-pudding": "^3.5.1",
"fs-extra": "^7.0.0",
"libnpm": "^2.0.1",
"npm-registry-fetch": "^3.8.0",
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 405b094

Please sign in to comment.