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

Allow for 3rd party commands #1584

Closed
Alxandr opened this issue Aug 20, 2018 · 6 comments
Closed

Allow for 3rd party commands #1584

Alxandr opened this issue Aug 20, 2018 · 6 comments

Comments

@Alxandr
Copy link

Alxandr commented Aug 20, 2018

With lerna's new structure, the different subcommands to the CLI is implemented as separate packages, all using a shared Command base class, which is available through it's own package. This lends itself very well to allowing third-party subcommands. The exact resolution strategy for finding these commands would need to be specced out, but I suggest something like the following:

  1. Find root lerna project (if not in a lerna project, bail and return no external commands).
  2. Go through all direct deps (dependencies and devDependencies), and find their package.json.
  3. Check for lerna.command key in package.json (nested, so it would be {"lerna": {"command":"...."}}).
  4. Add to yargs .command(require(path.resolve(path.dirname(pkgJsonPath, pkg.lerna.command)))). (though, probalby to some check wrt names, to avoid clashes, and other validation).

Things to note:

  • This will only work on lerna projects (you cannot use custom commands to init, nor global install custom commands).
  • It will only find commands in listed direct dependencies - you won't accidentally get new commands as dependnecies of other packages. This will also make name clashes way less of a potential issue.

All in all, I think a basic implementation of this feature can be done fairly easily. If this is something that's wanted/would be accepted, I'm willing to work on this feature.

@evocateur
Copy link
Member

Thanks for opening this issue, it's something I've thought about too.

I'm personally leaning more toward the git-<subcommand> approach, which will resolve git-mycmd on the $PATH when git mycmd is called. (I've been googling for 20 minutes trying to find formal documentation, but so far only blog posts :P. Edit: tons of examples here)

So third-party lerna commands in this scheme would simply need to provide a lerna-<cmdname> executable, which would be located in the local node_modules/.bin that npm creates when you install a dependency with a bin field.

Here's the steps I envisioned, roughly:

  1. Hook yargs' error handler to catch "missing commands"
  2. If caught, attempt to resolve lerna-<missingCommand> with which + npm-run-path
  3. If found, call the executable with the current argv, otherwise error like normal ("did you mean?", etc)

This "dashed-prefix" approach has admittedly more potential for namespace clobbering, but in practice I think it would be a lot easier to contribute to? It would remove the necessity for custom metadata per-package, and could even support global installations of custom commands. This approach would require extracting a "setup all the global lerna cli stuff except for adding commands" package, but that's something that should probably already exist anyway, given my previously-expressed goal of helpful modularity.

A sketch of a third-party command executable:

'use strict';

const lernaCli = require('@lerna/cli');
const myCmd = require('../lib/my-cmd');
// myCmd is a yargs command module

// lernaCli() returns a yargs instance,
// which is then chained as desired...
const cli = lernaCli().command(myCmd);

// call parse() to execute after configuration
cli.parse(process.argv.slice(2));

evocateur added a commit that referenced this issue Aug 22, 2018
…package

This moves a step closer to the ideal of enabling third-party commands in the git manner.

Refs #1584
@Alxandr
Copy link
Author

Alxandr commented Aug 22, 2018

Yargs actually support git-style sub-commands. The reason I tend to favor loading the commands (instead of spawning sub-processes) is the fact that you can flow context much better, because you can pass down stuff like the Project object from the Cli itself to a command, and it can just be part of the contract.

@evocateur
Copy link
Member

If you're extending the base Command class, you already get this.project and all the trimmings. None of the current commands "flow context" in the manner you describe.

As a contributor to yargs, it's news to me that it supports git-style subcommands out of the box. In any case, there's a neat trick I learned from npx that lets you replace the current process with a different cli, akin to exec in bash, so we don't have to worry about wrangling subprocesses.

@Alxandr
Copy link
Author

Alxandr commented Aug 22, 2018

I'm on mobile and completely forgot the "as far as I know" part of that statement. I'm pretty sure I read it in the docs, but I might remember wrong, so sorry about that. I'll try to look it up tomorrow.

@jd-carroll
Copy link
Contributor

Has anyone successfully contributed third-party commands to lerna? If so, has that been through a process of contributing a command to the lerna cli like npx lerna <my-custom-command> or through a process of writing your own cli which extends the lerna classesnpx my-cli <my-custom-command>?

@JamesHenry
Copy link
Member

Hi Folks 👋

This issue doesn't seem to have gained much traction. In order to allow our small team to focus on what matters most to Lerna v6 users in late 2022, I'm going to close this one. We do not currently have plans to support custom commands in lerna and are instead focusing on making the existing commands the best they can be. If there is a strong call from the community on this we certainly may reconsider.

If you have any other requests that could enhance your usage of Lerna 6, then please do let us know by opening a new discussion (for a feature) or issue (for a bug report) with as much context as possible.

You can also check out our published roadmap for Lerna v7 here: #3410

Many thanks 🙏

@JamesHenry JamesHenry closed this as not planned Won't fix, can't repro, duplicate, stale Nov 29, 2022
@lerna lerna locked and limited conversation to collaborators Nov 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants