feat: implement lerna add <pkg>[@version] [--dev]#1069
feat: implement lerna add <pkg>[@version] [--dev]#1069evocateur merged 15 commits intolerna:masterfrom
Conversation
|
Is there anything stopping this being merged? |
evocateur
left a comment
There was a problem hiding this comment.
Thanks for taking this on, @marionebl!
My apologies for the delay in review, I've been slammed at work.
|
|
||
| When run, this command will: | ||
|
|
||
| 1. Add `package` to each applicable package. Applicable are packages that are not `package` and are in scope |
There was a problem hiding this comment.
We also need to support arbitrary 3rd-party packages, too. If --hoist is enabled, the external dependency should be installed in the root package.json first.
Guarding against installing a local dependency inside itself is good.
There was a problem hiding this comment.
(it occurs to me that the --hoist behaviour is already dealt with by calling bootstrap at the end of execute, as long as we are also passing along this.options instead of the flags)
There was a problem hiding this comment.
Addressed installing external dependencies via 4be0d91.
Does make a lot more sense from the user perspective, thanks for the review 👍 .
The change got bigger than I'd like due to the fact I switched to an async control flow.
This is needed due to the network requests we send to determine the correct remote package version ranges to persist.
There was a problem hiding this comment.
This type of thing could be easier to build with async - await. Is there a reason is not used in the codebase so far?
|
|
||
| _logError(method, description, err) { | ||
| log.error(method, description); | ||
|
|
src/commands/AddCommand.js
Outdated
| }; | ||
|
|
||
| export function handler(argv) { | ||
| new AddCommand([argv.script, ...argv.args], argv, argv._cwd) |
src/commands/AddCommand.js
Outdated
| return false; | ||
| } | ||
|
|
||
| constructor(input, flags, cwd) { |
There was a problem hiding this comment.
Command subclasses don't need constructors, it's all handled in the superclass.
src/commands/AddCommand.js
Outdated
|
|
||
| const source = FileSystemUtilities.readFileSync(manifestPath); | ||
|
|
||
| const file = new JSONFile(manifestPath, source); |
There was a problem hiding this comment.
Is it really necessary to add JSONFile? You should be using write-pkg, an existing dependency, to write the package.json back to disk, as it already handles alphabetizing the updated (dev-)dependencies.
If you use read-pkg instead of reading the string, you can just merge applicable into the targeted dependencyType and write it back without testing, since the serialization is always alphabetized anyway.
const manifestJson = readPkg.sync(manifestPath, { normalize: false });
const manifestDeps = manifestJson[dependencyType] || {};
// overwrite updated dependencies
manifestJson[dependencyType] = {
...manifestDeps,
...applicable,
};
writePkg.sync(manifestPath, manifestJson);There was a problem hiding this comment.
I used json-file-plus to preserve package.json formatting. As this differs in behaviour from npm and other lerna commands and does not handle key alphabetization, I'll refactor as outlined.
src/commands/AddCommand.js
Outdated
| } | ||
|
|
||
| packageSatisfied(name, versionRange) { | ||
| const pkg = this.packages.find(pkg => pkg.name === name); |
There was a problem hiding this comment.
Wondering why not const pkg = this.getPackage(name); here?
| } | ||
|
|
||
| getPackage(name) { | ||
| return this.packages.find(pkg => pkg.name === name); |
There was a problem hiding this comment.
This and the body of packageExists() seems to wish this.packages was aMap()<String(name), Package>...
...or maybe Set()<Package>? Noodling for higher-level refactoring, no worries in this PR.
There was a problem hiding this comment.
I had the impression that iterating over all (filtered) packages was more common in the code base, and <Package>[] makes that very easy.
|
|
||
| expect.extend(pkgMatchers); | ||
|
|
||
| describe("AddCommand", () => { |
There was a problem hiding this comment.
These are brilliant tests, thanks!
test/helpers/pkgMatchers.js
Outdated
| @@ -0,0 +1,50 @@ | |||
| import semver from "semver"; | |||
|
|
|||
| const matchDependency = dependecyType => { | |||
There was a problem hiding this comment.
should be dependencyType. I go cross-eyed typing "dependency" a lot 😭
test/integration/lerna-add.test.js
Outdated
| expect(pkgs['package-4']).toDependOn('@test/package-1'); | ||
| }); | ||
|
|
||
| test("add to scoped package", async () => { |
There was a problem hiding this comment.
Given the current functionality, I'm not sure we need any more integration tests beyond the first. (variations based on args and whatnot are already covered in unit tests)
6ab20aa to
69672e1
Compare
* adresses lerna#998 * implement AddCommand * add AddCommand unit tests * add lerna-add integration tests * add pkgMatchers for better manifest assertions
2f04b10 to
9254413
Compare
|
Sorry for the force push, I should really stop trying to use the dumb Github UI for resolving merge conflicts (it never, ever works)... |
|
Thank you for for adding this feature @marionebl! I noticed that placing ## not in a mono-repo
yarn add something --dev ## works
yarn add --dev something ## works
## monorepo
lerna add something --dev ## works
lerna add --dev something ## ERROR: Missing list of packages to add to your project.Should not |
|
Created a new issue #1386 |
|
This thread has been automatically locked because there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Description
Given
Motivation and Context
addas first step,removeandupgradein separate PRs?Before
<dependency>to<depending>/package.jsonby handlerna bootstrap --scope=<depending>After
lerna add <dependency> --scope=<depending>How Has This Been Tested?
Types of changes
Checklist: