DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Edited on • Originally published at thinkthroo.com

1

Citty, an elegant CLI builder by Unjs

In this article, we will review the Citty, an elegant CLI builder. This library is built by Unjs.

Image description

I came across this package in cli.ts in unbuild. Let’s see this in action by running some experiments in codesandbox.

I copied the code below, provided in citty docs, in a codesandbox project.

import { defineCommand, runMain } from "citty";

const main = defineCommand({
  meta: {
    name: "hello",
    version: "1.0.0",
    description: "My Awesome CLI App",
  },
  args: {
    name: {
      type: "positional",
      description: "Your name",
      required: true,
    },
    friendly: {
      type: "boolean",
      description: "Use friendly greeting",
    },
  },
  run({ args }) {
    console.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
  },
});

runMain(main);
Enter fullscreen mode Exit fullscreen mode

and below image shows the outcome.

Link to codesandbox — https://codesandbox.io/p/devbox/vlmqqv

Pretty straightforward right? let’s now review how this is implemented in cli.ts in unbuild source code.

#!/usr/bin/env node
import { defineCommand, runMain } from "citty";
import consola from "consola";
import { resolve } from "pathe";
import { name, version, description } from "../package.json";
import { build } from "./build";

const main = defineCommand({
  meta: {
    name,
    version,
    description,
  },
  args: {
    dir: {
      type: "positional",
      description: "The directory to build",
      required: false,
    },
    config: {
      type: "string",
      description: [
        "The configuration file to use relative to the current working directory.",
        "                 Unbuild tries to read `build.config` from the build `DIR` by default.",
        "",
      ].join("\n"),
    },
    watch: {
      type: "boolean",
      description: "Watch the src dir and rebuild on change (experimental)",
    },
    stub: {
      type: "boolean",
      description: "Stub the package for JIT compilation",
    },
    minify: {
      type: "boolean",
      description: "Minify build",
    },
    sourcemap: {
      type: "boolean",
      description: "Generate sourcemaps (experimental)",
    },
    parallel: {
      type: "boolean",
      description:
        "Run different types of builds (untyped, mkdist, Rollup, copy) simultaneously.",
    },
  },
  async run({ args }) {
    const rootDir = resolve(process.cwd(), args.dir || ".");
    await build(rootDir, args.stub, {
      sourcemap: args.sourcemap,
      config: args.config ? resolve(args.config) : undefined,
      stub: args.stub,
      watch: args.watch,
      rollup: {
        esbuild: {
          minify: args.minify,
        },
      },
    }).catch((error) => {
      consola.error(`Error building ${rootDir}: ${error}`);
      throw error;
    });
  },
});

runMain(main);
Enter fullscreen mode Exit fullscreen mode

In the example provided in the documentation, there were two argument

  • friendly

  • name

But the cli.ts has arguments specific to unbuild:

  • dir — string

  • config — string

  • watch — boolean

  • stub — boolean

  • minify — boolean

  • sourcemap — boolean

  • parallel — boolean

run

async run({ args }) {
    const rootDir = resolve(process.cwd(), args.dir || ".");
    await build(rootDir, args.stub, {
      sourcemap: args.sourcemap,
      config: args.config ? resolve(args.config) : undefined,
      stub: args.stub,
      watch: args.watch,
      rollup: {
        esbuild: {
          minify: args.minify,
        },
      },
    }).catch((error) => {
      consola.error(`Error building ${rootDir}: ${error}`);
      throw error;
    });
  },
Enter fullscreen mode Exit fullscreen mode

All the options passed via CLI are used in build function as a parameter. build function is imported from ‘build.ts’ function.

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github — https://github.com/ramu-narasinga

My website — https://ramunarasinga.com

My Youtube channel — https://www.youtube.com/@ramu-narasinga

Learning platform — https://thinkthroo.com

Codebase Architecture — https://app.thinkthroo.com/architecture

Best practices — https://app.thinkthroo.com/best-practices

Production-grade projects — https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/unjs/citty

  2. https://github.com/unjs/unbuild/blob/main/src/cli.ts#L2C41-L2C46

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Image of DataStax

Langflow: Simplify AI Agent Building

Langflow is the easiest way to build and deploy AI-powered agents. Try it out for yourself and see why.

Get started for free

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay