In this article, we will review the Citty, an elegant CLI builder. This library is built by Unjs.
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);
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);
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; }); },
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
Top comments (0)