搭建自己的cli模板

本文详细介绍了如何从头创建一个名为'zhizu-cli'的命令行工具,包括初始化项目、配置package.json、实现命令行接口、处理用户输入、下载模板、安装依赖以及发布和测试过程。通过这个过程,读者可以学习到如何构建自己的Node.js CLI工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建文件夹zhizu-cli

初始化项目

  • npm init -y 或 yarn init -y

  • 在package.json中添加

    "bin": {
        "zhizu": "./index.js"
      },
    
  • 执行 npm link 这样就可以在全局自行zhizu命令

  • 出现下图,说明执行成功
    在这里插入图片描述

在项目中创建入口文件

  • index.js

    #!/usr/bin/env node
    // 读取packgaejson
    const packageConfig = require('./package.json')
    const init = require('./actions/init')
    
    const { program } = require('commander');
    
    // 这样输出-V或--version就能看到版本号了
    program.version(packageConfig.version)
    
    // 使用zhizu init my
    program
      .command('init <name> [destination]')
      .description('init a project')
      .action((name) => {
        init(name)
      });
    
    // program.option('-ig,--initgit', 'init git');
    
    program.parse(process.argv);
    

action 文件夹下

  • init.js
const path = require('path');
const fs = require('fs-extra');
const inquirer = require('inquirer');
const shell = require('shelljs');
const {
    successLog,
    markLog
} = require('../utils/log')
const {
    down
} = require('../utils/downTemplate');
const templatesJson = require('../config/templates/templates.json');
const exit = require('../utils/exit');
const os = require('os');
const ora = require('ora')
const spiner = ora('下载依赖')

const promptList = []
const init = async name => {
    // 获取当前执行命令的路径
    const cwd = process.cwd();
    const target = path.resolve(cwd, name || '.')
    // 获取可选模板
    const templates = {
        ...templatesJson
    }
    const keys = Object.keys(templates)
    let tmpSwitch = {
        type: 'list',
        name: 'template',
        message: '请选择下方的模板?',
        choices: keys
    }
    promptList.unshift(tmpSwitch)

    if (fs.existsSync(target)) {
        exit('当前路径下已存在该文件夹');
    }

    // 开启选择命令
    inquirer.prompt(promptList).then(async (answers) => {
        const {
            template
        } = answers
        const templateUrl = templates[template]
        try {
            // 拉取模板
            await down(templateUrl, name);
            // afterDown(name, answers);
            npmInstall(name, target)
        } catch (error) {
            exit(error.message);
        }
    })
}
const npmInstall = (name, target) => {
    shell.cd(target.replace(/\\/g,'/'))
    spiner.start()
    shell.exec('yarn', function (code, stdout, stderr) {
                console.log('3333333333')
                console.log(code, stdout, stderr)
                spiner.stop()
                success(name)
            });
}

const success = (name) => {
    successLog('success');
    markLog(`${name} 创建成功`);
    successLog('执行下面命令启动项目');
    successLog(`cd ${name}`);
    successLog('npm run serve');
    // markLog(`cd ${name}`);
    // markLog('npm install');
    // markLog('npm run serve');
    // if (os.type() == 'Windows_NT') {
    //     //windows
    //     markLog('请在git bash 中执行 npm run lf');
    // }
}

module.exports = init

在这里插入图片描述

config 文件夹

  • templates.json
{
    "zhizu-admin":"direct:git地址#分支名称",
    "zhizu-uni":"direct:git地址#分支名称",
    "zhizu-h5":"direct:git地址#分支名称"
}

utils 文件夹

  • downTemplate.js
const download = require('download-git-repo');
const { markLog, errorLog, successLog } = require('./log');
// const spiner = require('./spinner');
const ora = require('ora')
const spiner = ora('下载中')
/**
 * 下载模板
 * @param {*} url git下载地址
 * @param {*} name 项目名称
 * @returns 
 */
const down = (url, name) =>{
    // spiner.start();
    // markLog('下载中');
    spiner.start()
    return new Promise((resolve, reject) =>{
        download(url,name,{ clone: true }, (err) => {
            if(err){
                // spiner.fail();
                spiner.fail()
                errorLog('下载失败');
                reject(err);
            }else{
                // spiner.succeed();
                spiner.stop()
                successLog('下载模板完毕');
                resolve();
            }
        })
    })
}

module.exports = {
    down
}
  • exit.js
const {errorLog} = require("./log");

const exit = (msg) => {
    errorLog(msg);
    process.exit(1);
}

module.exports = exit;
  • index.js
const path = require('path');
const fs = require('fs-extra')
const chalk = require('chalk')
const symbols = require('log-symbols')
const _ = require('lodash')
const customregist = require('../json/customregist.json')
const registries = require('../json/registries.json')
/**
 * 当前cli所在路径
 */
// const cliPath = path.resolve(".")

/**
 * 
 * @param {*} filepath file路径,需要带/,默认拼接cli所在路径cliPath
 * @param {*} object 需要写入的对象
 */
function wirteSync (filepath, jsonObject) {
    fs.writeFileSync(filepath, JSON.stringify(jsonObject, null, '\t'))
}
/**
 * 
 * @param {*} message 成功打印
 */
function successConsole (message) {
    console.log(chalk.green(message))
}

/**
 * 
 * @param {*} message 错误打印
 */
function errorConsole (message) {
    console.log(symbols.error, chalk.red(message))
}
/**
 * 
 * @param {*} url git地址转成可下载地址
 */
function gitTogitdown (url) {
    // 最后的地址格式
    // 域名:所有者/项目名称#分支
    // 例如https://gitea.51trust.com:front/vueDemo#master
    // "vue":"https://gitea.51trust.com:front/vueDemo#master",
    // "vue2":"https://gitea.51trust.com/front/vueDemo.git"
    // let tmpUrl = _.replace(url, ".git", "#master")
    // let tmpArray = _.split(tmpUrl, '/');
    // let result = tmpArray[0] + "//" + tmpArray[2] + ":" + tmpArray[3] + "/" + tmpArray[4]
    return url
}

/**
 * 获取所有template
 */
function getAllTemplates(){
    let all = {
        ...registries,
        ...customregist,
    }
    return all
}

module.exports = {
    wirteSync,
    successConsole,
    errorConsole,
    gitTogitdown,
    getAllTemplates
}
  • log.js
const chalk = require('chalk');
const figlet = require('figlet');

const warnLog = (msg) => {
    console.log(chalk.yellow(msg))
}

const errorLog = (msg) => {
    console.log(chalk.red(msg))
}

const successLog = (msg) => {
    console.log(chalk.green(msg))
}

const markLog = (msg) => {
    console.log(chalk.magenta(msg))
}

const figletLog = (msg,callback) => {
    figlet(msg,(err, result)=>{
        successLog(result);
        callback && callback();
    });
}

module.exports = {
    warnLog,
    errorLog,
    successLog,
    markLog,
    figletLog
}

打包发布

  • npm login
  • 输入用户名,密码,邮箱
  • npm publish
  • 删除本地测试执行的zhizu-cli npm rm --global zhizu-cli
  • 全局安装依赖 npm i zhizu-cli -g
  • 测试执行 zhizu init packageName
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值