Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(package): .serialize() also writes package-lock version #2160

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 50 additions & 2 deletions core/package/__tests__/core-package.test.js
Expand Up @@ -2,11 +2,15 @@

jest.mock("load-json-file");
jest.mock("write-pkg");
jest.mock("write-json-file");
jest.mock("fs");

const os = require("os");
const path = require("path");
const loadJsonFile = require("load-json-file");
const writePkg = require("write-pkg");
const writeJsonFile = require("write-json-file");
const fs = require("fs");

// file under test
const Package = require("..");
Expand All @@ -29,6 +33,13 @@ describe("Package", () => {
});
});

describe("get .lockFileLocation", () => {
it("should return the package-lock location", () => {
const pkg = factory({ name: "lock-file-location" });
expect(pkg.lockFileLocation).toBe(path.normalize("/root/path/to/lock-file-location/package-lock.json"));
});
});

describe("get .resolved", () => {
it("returns npa.Result relative to rootPath, always posix", () => {
const pkg = factory({ name: "get-resolved" });
Expand Down Expand Up @@ -257,8 +268,11 @@ describe("Package", () => {
});

describe(".serialize()", () => {
it("writes changes to disk", async () => {
writePkg.mockImplementation(() => Promise.resolve());
it("writes changes to package.json to disk", async () => {
writePkg.mockImplementationOnce(() => Promise.resolve());
fs.existsSync.mockImplementationOnce(() => false);
writeJsonFile.mockImplementationOnce(() => Promise.resolve());
loadJsonFile.mockImplementationOnce(() => Promise.resolve());

const pkg = factory({ name: "serialize-me" });
const result = await pkg.set("woo", "hoo").serialize();
Expand All @@ -271,6 +285,40 @@ describe("Package", () => {
woo: "hoo",
})
);
expect(fs.existsSync).toHaveBeenCalledWith("/root/path/to/serialize-me/package-lock.json");
expect(loadJsonFile).not.toHaveBeenCalled();
expect(writeJsonFile).not.toHaveBeenCalled();
});

it("writes changes to package-lock to disk", async () => {
writePkg.mockImplementationOnce(() => Promise.resolve());
fs.existsSync.mockImplementationOnce(() => true);
writeJsonFile.mockImplementationOnce(() => Promise.resolve());
loadJsonFile.mockImplementationOnce(() => Promise.resolve({ name: "something" }));

const pkg = factory({ name: "serialize-me-lock", version: "1.0.0" });
expect(pkg.version).toBe("1.0.0");

const result = await pkg.set("version", "2.0.0").serialize();
expect(result).toBe(pkg);
expect(result.version).toBe("2.0.0");

expect(writePkg).toHaveBeenLastCalledWith(
pkg.manifestLocation,
expect.objectContaining({
name: "serialize-me-lock",
version: "2.0.0",
})
);
expect(fs.existsSync).toHaveBeenCalledWith("/root/path/to/serialize-me-lock/package-lock.json");
expect(loadJsonFile).toHaveBeenCalledWith("/root/path/to/serialize-me-lock/package-lock.json");
expect(writeJsonFile).toHaveBeenCalledWith(
"/root/path/to/serialize-me-lock/package-lock.json",
expect.objectContaining({
version: "2.0.0",
}),
{ detectIndent: true }
);
});
});
});
Expand Down
34 changes: 33 additions & 1 deletion core/package/index.js
Expand Up @@ -4,6 +4,9 @@ const npa = require("npm-package-arg");
const path = require("path");
const loadJsonFile = require("load-json-file");
const writePkg = require("write-pkg");
const fs = require("fs");
const writeJsonFile = require("write-json-file");
const pWaterfall = require("p-waterfall");

// symbol used to "hide" internal state
const PKG = Symbol("pkg");
Expand All @@ -30,6 +33,12 @@ function shallowCopy(json) {
}, {});
}

// determine if a package-lock.json file exists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the appropriate place for lockfile maintenance. It's a function of the version command, not integral to the nature of a Package.

function hasPackageLock(location) {
const packageLock = path.resolve(location);
return fs.existsSync(packageLock);
}

class Package {
constructor(pkg, location, rootPath = location) {
// npa will throw an error if the name is invalid
Expand Down Expand Up @@ -77,6 +86,9 @@ class Package {
manifestLocation: {
value: path.join(location, "package.json"),
},
lockFileLocation: {
value: path.join(location, "package-lock.json"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be npm-shrinkwrap.json, or yarn.lock, or, or, or...

},
nodeModulesLocation: {
value: path.join(location, "node_modules"),
},
Expand Down Expand Up @@ -181,7 +193,27 @@ class Package {
* @returns {Promise} resolves when write finished
*/
serialize() {
return writePkg(this.manifestLocation, this[PKG]).then(() => this);
return writePkg(this.manifestLocation, this[PKG])
.then(() => this.writePkgLock())
.then(() => this);
}

/**
* Write package-lock changes to disk
* @returns {Promise} resolves when write finished
*/
writePkgLock() {
// We only care about version in the lock file; a package's name never changes
const lockChanges = { version: this[PKG].version };

const tasks = [
() => loadJsonFile(this.lockFileLocation),
lockFileData => Promise.resolve(Object.assign({}, lockFileData, lockChanges)),
updatedLockFileData =>
writeJsonFile(this.lockFileLocation, updatedLockFileData, { detectIndent: true }),
];

return hasPackageLock(this.lockFileLocation) ? pWaterfall(tasks) : Promise.resolve();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need p-waterfall just to chain promises. This check should be done way earlier, too.

}

/**
Expand Down
2 changes: 2 additions & 0 deletions core/package/package.json
Expand Up @@ -33,6 +33,8 @@
"dependencies": {
"load-json-file": "^4.0.0",
"npm-package-arg": "^6.1.0",
"p-waterfall": "2.1.0",
"write-json-file": "4.1.0",
"write-pkg": "^3.1.0"
}
}