DEV Community

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

Posted on • Updated on

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

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 parts 2.0 to 2.3, we looked at different functions involved to check if there is an existing config.

Let’s move on to the next line of code

After checking if there is an existing config, in the getProjectConfig function, the next step is to find out the project type.

This project type is your project’s type in which you are trying to install shadcn-ui components via init command.

const projectType = await getProjectType(cwd)
Enter fullscreen mode Exit fullscreen mode

getProjectType is imported from ui/packages/cli/src/utils/get-project-info.ts and this function has some checks to identify if your Next.js project uses app or pages router and if it has src folder.

export async function getProjectType(cwd: string): Promise<ProjectType | null> {
  const files = await fg.glob("\*\*/\*", {
    cwd,
    deep: 3,
    ignore: PROJECT\_SHARED\_IGNORE,
  })

  const isNextProject = files.find((file) => file.startsWith("next.config."))
  if (!isNextProject) {
    return null
  }

  const isUsingSrcDir = await fs.pathExists(path.resolve(cwd, "src"))
  const isUsingAppDir = await fs.pathExists(
    path.resolve(cwd, \`${isUsingSrcDir ? "src/" : ""}app\`)
  )

  if (isUsingAppDir) {
    return isUsingSrcDir ? "next-app-src" : "next-app"
  }

  return isUsingSrcDir ? "next-pages-src" : "next-pages"
}
Enter fullscreen mode Exit fullscreen mode

This code is pretty self-explanatory except for the fg.glob

const files = await fg.glob("\*\*/\*", {
    cwd,
    deep: 3,
    ignore: PROJECT\_SHARED\_IGNORE,
})
Enter fullscreen mode Exit fullscreen mode

Check out the fast-glob docs about the deep property.

You might be wondering what’s PROJECT_SHARED_IGNORE.

Well, PROJECT_SHARED_IGNORE is an array initiated at the top of file.

Check out the docs for ignore property.

Conclusion:

As I moved on to the next line of code in getProjectConfig in shadcn-ui CLI source code, I found a function named getProjectType. This function’s purpose is to find out if your Next.js project uses app or pages router and whether it has src folder.

This code is pretty self explanatory:

export async function getProjectType(cwd: string): Promise<ProjectType | null> {
  const files = await fg.glob("\*\*/\*", {
    cwd,
    deep: 3,
    ignore: PROJECT\_SHARED\_IGNORE,
  })

  const isNextProject = files.find((file) => file.startsWith("next.config."))
  if (!isNextProject) {
    return null
  }

  const isUsingSrcDir = await fs.pathExists(path.resolve(cwd, "src"))
  const isUsingAppDir = await fs.pathExists(
    path.resolve(cwd, \`${isUsingSrcDir ? "src/" : ""}app\`)
  )

  if (isUsingAppDir) {
    return isUsingSrcDir ? "next-app-src" : "next-app"
  }

  return isUsingSrcDir ? "next-pages-src" : "next-pages"
}
Enter fullscreen mode Exit fullscreen mode

Except for the way files are accessed. fg.glob is set to depth level of 3 and ignores certain folders such as node_modules, dist, build, public and .next.

From the code snippet above, there’s one of 5 values expected as a project type: null || “next-app-src” || “next-app” || “next-pages-src” || “next-pages”.

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/utils/get-project-info.ts#L111
  2. https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/utils/get-project-info.ts#L24

Top comments (0)