前言
大家好,我是JS-Man
今天教大家重复造轮子,呸,是教大家怎么敲脚手架命令行。 ps:本文只涉及命令行的开发,不涉及脚手架模版的开发,如下图:

其实非常简单,学会了又能出去吹牛了哈哈哈🤣,本文使用lerna的架构,感兴趣的可以先了解一下。
以下是开发命令行的步骤:
- commander创建命令,获取用户输入option
- 用户选择模版项目类型
- 拉取gitlab模版,处理编译
- 彩蛋:llm模版,拉取接口文档,数据处理,添加到prompt.md
1. commander创建命令
以下是lerna的目录结构:

我们在service-cli里进行开发,先使用commander创建基本的命令:
js
const program = require('commander')
program
.command('create <app-name>')
.alias('c')
.option('-p, --private', 'if template is private, need access token')
.option('-g, --groupId <groupId>', 'search template projects from groupId')
.description('create a new project powered by ks-server-cli')
.action((name) => {
require('./create')(name, minimist(process.argv.slice(3)))
})
2. 用户选择模版项目类型
使用inquirer处理用户输入:
js
const inquirer = require('inquirer')
// 让用户选择项目类型
const { currentProjectType } = await inquirer.prompt({
name: 'currentProjectType',
type: 'list',
choices: ['移动端', 'PC端'],
message: '请选择当前创建项目的类型',
})
3. 拉取gitlab模版,处理编译
先使用ora封装一个等待加载的loading:
js
const ora = require('ora')
exports.waitLoading =
(message, fn, isempty) =>
async (...args) => {
const spinner = ora(message)
spinner.start()
const data = await fn(...args)
if (data || isempty) {
spinner.succeed(`${message} successfully`)
return data
} else {
spinner.fail(`${message} error`)
}
}
再使用download-git-repo进行下载
js
const sourcePath = await waitLoading(
'downloading template',
downloadTemplate
)(id, currentTemplateProjName, defaultTags, headers)
/**
* 下载项目模版到本地目录
*/
let DownloadGitRepo = promisify(require('download-git-repo'))
const downloadTemplate = async (
projectId,
templateName,
templateTag,
headers
) => {
try {
const token = headers['PRIVATE-TOKEN'] ? headers['PRIVATE-TOKEN'] : ''
const url = `xxx`
// 2.拼接存储下载好的模板的路径
const destPath = `${downloadDirPath}/${templateName}`
// 3.下载模板
await DownloadGitRepo(url, destPath)
// 4.将保存模板的路径返回给调用者
return destPath
} catch (error) {
console.log(error)
}
}
4. llm模板,处理接口文档
以上步骤做完后已经可以完成脚手架命令行的开发了,最近使用cursor的claude-4-sonnet开发项目效率确实翻倍了,很多简单的管理后台项目通过prompt基本上几个小时就可以完成。 于是我在想,能不能将这一套开发流程梳理下。 在脚手架里内置好一个prompt.md,将产品原型和接口文档写进去后,直接交给cursor去完成,prompt的模板如下:
- 产品文档详细内容:
- 补充说明:
- 接口文档:
我们这里要做的就是将接口文档处理好后,补充到里面。
针对以上步骤,拉取llm模板后,增加拉取接口文档命令:
js
const { kapiUrl } = await inquirer.prompt({
name: 'kapiUrl',
type: 'input',
message: '请输入接口文档地址',
validate: (value) => {
if (!value) {
return '请输入接口文档地址'
}
if (!value.startsWith('http')) {
return '请输入正确的接口文档地址'
}
return true
}
})
从公司内部接口文档里调接口获取文档内容,也可以使用自动化库如playwright等进行爬取,当然有接口肯定是最好的。拉取成功后再进行数据处理:
js
// 生成markdown文档的函数
function generateMarkdown(data) {
const { title, path, method, req_headers, req_body_other, res_body } = data
let markdown = `# ${title}\n\n`
// 基本信息
markdown += `## 基本信息\n\n`
markdown += `- **接口路径**: \`${path}\`\n`
markdown += `- **请求方法**: \`${method}\`\n\n`
// 请求头
if (req_headers && req_headers.length > 0) {
markdown += `## 请求头\n\n`
markdown += `| 参数名 | 示例值 | 必填 | 说明 |\n`
markdown += `|--------|--------|------|------|\n`
req_headers.forEach(header => {
markdown += `| ${header.name || ''} | ${header.value || ''} | ${header.required === '1' ? '是' : '否'} | ${header.desc || ''} |\n`
})
markdown += `\n`
}
// 请求参数
if (req_body_other) {
markdown += `## 请求参数\n\n`
markdown += `\`\`\`json\n`
markdown += `${req_body_other}\n`
markdown += `\`\`\`\n\n`
}
// 返回数据
if (res_body) {
markdown += `## 返回数据\n\n`
markdown += `\`\`\`json\n`
markdown += `${res_body}\n`
markdown += `\`\`\`\n\n`
}
// 生成时间
markdown += `---\n\n`
markdown += `> 文档生成时间: ${new Date().toLocaleString('zh-CN')}\n`
return markdown
}
catData.list.forEach(item => {
// 提取接口信息
const {
title,
path: apiPath,
req_headers,
req_body_other,
method,
res_body
} = item
// 生成markdown内容
const markdownItem = generateMarkdown({
title,
path: apiPath,
method,
req_headers,
req_body_other,
res_body
})
markdownContent += markdownItem
})
总结
以上就是脚手架命令行的开发过程,文中只列举了关键步骤,因为是公司内部项目,所以不能贴详细代码。
实测llm模板开发简单的pc管理后台成功率90%,生成后5次左右的修改就开发完成了。