citty icon indicating copy to clipboard operation
citty copied to clipboard

CLI Plugins

Open pi0 opened this issue 1 year ago • 2 comments

inspired from https://github.com/unjs/citty/issues/98#issuecomment-2011718215 by @jgoux

With plugins, we can allow them to intercept to different hooks but also preserve their context. We can extend to more hooks if needed.

Example:

const telemetryPlugin = defineCittyPlugin(() => {
  const telemetry = new TelemetryClient();

  return {
    name: 'telemetry',
    async setup() {
      telemetry.init();
      await telemetry.captureEvent(`$command:${ctx.cmd.meta.name}:start`); 
    },
    async cleanup() {
      await telemetry.captureEvent(`$command:${ctx.cmd.meta.name}:end`);
      telemetry.flush();
    }
  }
})

defineCommand({
  meta: {
    name: "hello",
    version: "1.0.0",
    description: "My Awesome CLI App",
  },
  plugins: [telemetryPlugin],
  run({ args }) {
    console.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
  },
})

pi0 avatar Mar 21 '24 10:03 pi0

Sounds good to me! 👍

jgoux avatar Mar 21 '24 11:03 jgoux

Hello there, I was looking for a kind of interceptor/plugin for citty that I could hook without changing a command's code, and stumbled upon #98 and this issue. @Barbapapazes made some initial work on it, I was wondering if there was any other conversation to resume or abandon the idea?

My use case is the following:

There's a cli using citty, and we wanted to do a wrapper on top of it for a few commands of ours. So we import it's main defineCommand, merge with our commands and provide that to the main defineCommand as subcommands.

For a command ABC from said cli, I'd like it to invoke N commands/functions of mine before/after, but not touch anything the other CLI does because I want it's behavior to happen.

So, in that fashion, I think we can just make a setup() on our main defineCommand which will check the context.args._[0] to know which command was called and do what needs to be done before the other command runs for our case, and that should be enough.

But I was wondering if a plugin would look cleaner? idk. Visually the suggested approach felt just like vue2 mixin which I liked to use back then so I'm biased lol.

RaphaelDDL avatar Feb 21 '25 21:02 RaphaelDDL