Skip to content

Instantly share code, notes, and snippets.

@Ayc0
Last active July 13, 2022 23:27
Show Gist options
  • Save Ayc0/744c81032792a7d59454dc1f124f39a6 to your computer and use it in GitHub Desktop.
Save Ayc0/744c81032792a7d59454dc1f124f39a6 to your computer and use it in GitHub Desktop.
Yarn plugin experience

Mismatch between doc and CLI tool in real life

When reading https://yarnpkg.com/advanced/plugin-tutorial, it mentions this kind of code:

module.exports = {
  name: `plugin-hello-world`,
  factory: require => {
    const {BaseCommand} = require(`@yarnpkg/cli`);

    class HelloWorldCommand extends BaseCommand {
      static paths = [[`hello`]];

      async execute() {
        this.context.stdout.write(`This is my very own plugin 😎\n`);
      }
    }

    return {
      commands: [
        HelloWorldCommand,
      ],
    };
  }
};

It also recommends to use @yarnpkg/builder. But when doing so, it generates a TS file like so:

import {CommandContext, Plugin} from '@yarnpkg/core';
import {Command} from 'clipanion';

class HelloWorldCommand extends Command<CommandContext> {
  @Command.String(`--name`)
  name: string = `John Doe`;

  @Command.Path(`hello`, `world`)
  async execute() {
    console.log(`Hello ${this.name}!`);
  }
}

const plugin: Plugin = {
  hooks: {
    afterAllInstalled: () => {
      console.log(`What a great install, am I right?`);
    },
  },
  commands: [
    HelloWorldCommand,
  ],
};

export default plugin;

Here we can see that there is little to match between the 2 objects (commands seems to match but that's it)

Under the hood it seems that when using @yarnpkg/builder build that it converts back to the 1st format, but as a 1st timer, this is really confusing.

=> It could be indicated in the doc that the tool will auto format this and also prefix the name

Name constraints

When running yarn dlx @yarnpkg/builder@^2 new plugin test we got this output:

➀ YN0000: β”Œ Resolution step
➀ YN0060: β”‚ @yarnpkg/builder@npm:2.1.3 [dc3fc] provides @yarnpkg/core (p5cddb) with version 2.4.0, which doesn't satisfy what @yarnpkg/cli and some of its descendants request
➀ YN0060: β”‚ @yarnpkg/cli@npm:2.4.3 [9a834] provides @yarnpkg/plugin-pack (p02669) with version 2.2.3, which doesn't satisfy what @yarnpkg/plugin-npm requests
➀ YN0002: β”‚ root-workspace-0b6124@workspace:. doesn't provide typescript (p82744), requested by @yarnpkg/builder
➀ YN0000: β”‚ Some peer dependencies are incorrectly met; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code
➀ YN0000: β”” Completed in 5s 563ms
➀ YN0000: β”Œ Fetch step
➀ YN0000: β”” Completed in 0s 572ms
➀ YN0000: β”Œ Link step
➀ YN0000: β”” Completed in 8s 829ms
➀ YN0000: Done with warnings in 15s 65ms

Nothing tells us that we'll have to modify the name in the package.json to modify the name of the generated plugin.

Also, if we use a custom name in the package.json, like this-is-a-test (instead of the provided yarn-plugin-helloworld), and then run the build command, we get this error:

Usage Error: Invalid plugin name "this-is-a-test" - it should be "yarn-plugin-<something>"

$ builder build plugin [--no-minify]

But here are 2 issues:

  1. in https://yarnpkg.com/advanced/plugin-tutorial, there is no mention that plugins needs to respect a specific format,
  2. but also @<scope>/yarn-plugin-<name> seems to be valid, even if it's not mentioned neither in the docs, nor in the output command

Custom commands

From hooks, we get back objects like Project. But there is no indication for how to retrieve those in custom commands.

Hooks

In general, even if the list of hooks is documented in https://yarnpkg.com/advanced/plugin-tutorial, it's hard to know what are for, and how to use them. For instance here for afterAllInstalled: Project, InstallOptions aren't documented and "Called after the install method from the Project class successfully completed." is a bit vague.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment