CLI tool in Nue.Js source code.

In this article, we will review the how the CLI tool is written in Nue.js source code.
Nue.js CLI tool supports the below listed commands:
Help
Serve
Build
Create
Init
We will review Help, Init commands to understand the underlying pattern.
Help command
Let’s find out how help is printed to CLI. At line 126-133 in packages/nuejs/src/cli.js, you will find the below code:
// Only run main when called as real CLI
if (esMain(import.meta)) {
const args = getArgs(process.argv.slice(2))
// help
if (args.help) {
await printHelp()
// version
}
printHelp()
printHelp() is defined in the same cli.js file and has the below code:
async function printHelp() {
const { getHelp } = await import('./cli-help.js')
console.info(getHelp())
}
Check out the cli-help.js it contains the below code:
#!/usr/bin/env bun
import { esMain, log, colors, version, getEngine, openUrl } from './util.js'
// [-npe] --> [-n, -p, -e]
export function expandArgs(args) {
const arr = []
args.forEach(arg => {
if (arg[0] == '-' && arg[1] != '-' && arg[2]) {
arg.slice(1).split('').forEach(el => arr.push('-' + el))
} else {
arr.push(arg)
}
})
return arr
}
// TODO: tests
export function getArgs(argv) {
const commands = ['serve', 'build', 'init', 'create', 'docs']
const args = { paths: [], root: null }
let opt
expandArgs(argv).forEach((arg) => {
// skip
if (arg == '--') {
// test suite
} else if (arg.endsWith('.test.js')) {
args.test = true
// command
} else if (!args.cmd && commands.includes(arg)) {
args.cmd = arg
// options
} else if (!opt && arg[0] == '-') {
// booleans
if (['-p', '--production'].includes(arg)) args.is_prod = true
else if (['-v', '--version'].includes(arg) && !args.cmd) args.version = true
else if (['-n', '--dry-run'].includes(arg)) args.dryrun = true
else if (['-h', '--help'].includes(arg)) args.help = true
else if (['-v', '--verbose'].includes(arg)) args.verbose = true
else if (['-b', '--esbuild'].includes(arg)) args.esbuild = true
else if (['-l', '--lcss'].includes(arg)) args.lcss = true
else if (['-d', '--deploy'].includes(arg)) args.deploy = args.is_prod = true
else if (['-I', '--incremental'].includes(arg)) args.incremental = true
else if (['-o', '--open'].includes(arg)) args.open = true
// string values
else if (['-e', '--environment'].includes(arg)) opt = 'env'
else if (['-r', '--root'].includes(arg)) opt = 'root'
else if (['-P', '--port'].includes(arg)) opt = 'port'
else if (['-B', '--base'].includes(arg)) opt = 'base'
// bad options
else throw `Unknown option: "${arg}"`
} else if (arg && arg[0] != '-') {
if (opt) {
args[opt] = opt == 'port' ? Number(arg) : arg
// Number(alphabetic characters) is falsy. Check if port is really set:
if (opt != 'port' || (opt == 'port' && args.port)) opt = null
}
else args.paths.push(arg)
} else if (opt) throw `"${opt}" option is not set`
})
if (opt) throw `"${opt}" option is not set`
return args
}
async function printHelp() {
const { getHelp } = await import('./cli-help.js')
console.info(getHelp())
}
async function printVersion() {
log(`Nue ${version} ${colors.green('•')} ${getEngine()}`)
}
async function runCommand(args) {
if (args.cmd == 'docs') return openUrl('https://nuejs.org/docs/')
const { createKit } = await import('./nuekit.js')
const { cmd = 'serve', dryrun, deploy, root = null, port } = args
const init = cmd == 'init'
if (!root) args.root = '.' // ensure root is unset for create, if not set manually
console.info('')
await printVersion()
args.nuekit_version = version
// create nue
if (cmd == 'create') {
const { create } = await import('./create.js')
return await create({ ...args, root, port })
}
const nue = await createKit(args)
if (!nue) return
if (args.open) openUrl(`http://localhost:${nue.port}/`)
// deployer (private repo)
const { deploy: deployer } = deploy ? await import('nue-deployer') : {}
// build
if (init) {
await nue.init(true)
if (deploy) await deployer({ root: nue.dist, init: true })
} else if (dryrun || deploy || args.paths[0] || cmd == 'build') {
const paths = await nue.build(args.paths)
if (!dryrun && deploy && paths[0]) await deployer({ paths, root: nue.dist, init })
// serve
} else {
await nue.serve()
}
}
// Only run main when called as real CLI
if (esMain(import.meta)) {
const args = getArgs(process.argv.slice(2))
// help
if (args.help) {
await printHelp()
// version
} else if (args.version) {
await printVersion()
// command
} else if (!args.test) {
try {
await runCommand(args)
} catch (e) {
console.info(e)
}
}
}
Init command
At line 90 in cli.js, there is this below check:
async function runCommand(args) {
if (args.cmd == 'docs') return openUrl('https://nuejs.org/docs/')
const { createKit } = await import('./nuekit.js')
const { cmd = 'serve', dryrun, deploy, root = null, port } = args
const init = cmd == 'init'
At line 112 in the cli.js, you will find the below code:
if (init) {
await nue.init(true)
if (deploy) await deployer({ root: nue.dist, init: true })
}
nue.init? where is that coming from? you will see this below code at line 104
const nue = await createKit(args)
createKit
createKit is exported from nuekit.js and has 383 LOC at the time of writing this article. Since we are interested in init, I searched for “init” in this nuekit.js file and found the below code:
async function init(force) {
await initNueDir({ dist, is_dev, esbuild, force })
}
initNueDir is imported from a file named init.js. Similarly I saw create.js.
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:
Subscribe to my newsletter
Read articles from Ramu Narasinga directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

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