DEV Community

Cover image for shadcn-ui/ui codebase analysis: How does shadcn-ui CLI work? — Part 1.0
Ramu Narasinga
Ramu Narasinga

Posted on • Edited on

2

shadcn-ui/ui codebase analysis: How does shadcn-ui CLI work? — Part 1.0

I wanted to find out how shadcn-ui CLI works. In this article, I discuss the code used to build the shadcn-ui/ui CLI. In part 1, we will look at a code snippet picked from packages/cli/src/index.ts.

// source: https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/index.ts
#!/usr/bin/env node
import { add } from "@/src/commands/add"
import { diff } from "@/src/commands/diff"
import { init } from "@/src/commands/init"
import { Command } from "commander"

import { getPackageInfo } from "./utils/get-package-info"

process.on("SIGINT", () => process.exit(0))
process.on("SIGTERM", () => process.exit(0))

async function main() {
  const packageInfo = await getPackageInfo()

  const program = new Command()
    .name("shadcn-ui")
    .description("add components and dependencies to your project")
    .version(
      packageInfo.version || "1.0.0",
      "-v, --version",
      "display the version number"
    )

  program.addCommand(init).addCommand(add).addCommand(diff)

  program.parse()
}

main()
Enter fullscreen mode Exit fullscreen mode

There’s about 29 lines of code in index.ts

Imports used

#!/usr/bin/env node
import { add } from "@/src/commands/add"
import { diff } from "@/src/commands/diff"
import { init } from "@/src/commands/init"
import { Command } from "commander"

import { getPackageInfo } from "./utils/get-package-info"
Enter fullscreen mode Exit fullscreen mode

Shadcn CLI docs discuss three commands; add , diff , init

These commands are imported from a folder named commands in src folder.

Commander is an npm package used here to enable CLI interactions.

getPackageInfo

getPackageInfo is a small utility function found in utils/get-package-info.ts


import path from "path"
import fs from "fs-extra"
import { type PackageJson } from "type-fest"

export function getPackageInfo() {
  const packageJsonPath = path.join("package.json")

  return fs.readJSONSync(packageJsonPath) as PackageJson
}
Enter fullscreen mode Exit fullscreen mode

Notice how there’s an enforced PackageJson type from type-fest. It is from the Legend, Sindre Sorhus. I see this guy’s name so often when I dig into open source.

fs.readJSONSync reads a JSON file and then parses it into an object. In this case, it is an object of type PackageJson.

process.on("SIGINT", () => process.exit(0))
process.on("SIGTERM", () => process.exit(0))
Enter fullscreen mode Exit fullscreen mode

SIGINT: This is a signal that is typically sent to a process when a user types Ctrl+C in the terminal. It is often used to request that a process terminate gracefully. When a process receives a SIGINT signal, it can catch it and perform any necessary cleanup operations before terminating.

SIGTERM: This is a signal that is typically sent to a process by the operating system to request that the process terminate. It is often used as a graceful way to ask a process to terminate, allowing it to perform any necessary cleanup operations before exiting. Processes can catch this signal and perform cleanup operations before terminating. (Source)

Conclusion:

I have seen Commander.js being used in Next.js create-next-app package, I see it in use here again in shadcn-ui/ui. I will continue picking small code snippets from this CLI package and discuss the code. I liked the way package.json is read using a utility function getPackageInfo. This getPackageInfo uses fs.readJSONSync. There is Type assertion applied using PackageJson provided by type-fest on the Object returned by fs.readJSONSync.

Get free courses inspired by the best practices used in open source.

About me:

Website: https://ramunarasinga.com/

Linkedin: https://www.linkedin.com/in/ramu-narasinga-189361128/

Github: https://github.com/Ramu-Narasinga

Email: ramu.narasinga@gmail.com

Learn the best practices used in open source.

References:

  1. https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/index.ts
  2. https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/utils/get-package-info.ts#L5
  3. https://dev.to/superiqbal7/graceful-shutdown-in-nodejs-handling-stranger-danger-29jo

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →