手写cli

大家好,今天分享一篇手写cli:

  

 

 

index.js

const { program } = require('commander')

const { version } = require('../package.json')

const del = require('del')
const path = require('path')

program.version(version)

// const delFunc = async (name) => {
//     const dir = path.resolve('.')
//     await del(dir + '/' + name)
// }

// program
//     .option('-c, --create','create a project')
//     .option('-i, --init <type>','init a project with a name!')
//     .option('-d, --delete <file>','delete a file', delFunc)
// //创建子命令
// program
//     .command('clone <source> [destination]')
//     .option('-i, --inifo', 'clone info')
//     .description('clone a repository into a newly created directory')
//     .action((source,destination,obj) => {
//         console.log('source',source);
//         console.log('des',destination)
//         console.log(obj);
//     })

// console.log('hello world! Hello cli!')

const mapActions = {
    init:{
        alias:'i',
        desc:'create/init a project',
        examples:[
            'terry init <projectName>',
            'terry i <projectName>'
        ]
    },
    remove:{
        alias:'rm',
        desc:'remove files from path',
        examples:[
            'terry rm -f <filepath>',
            'terry rm <filepath>'
        ]
    },
    '*':{
        alias:'',
        desc:'command not found!',
        examples:[]
    }
}

Reflect.ownKeys(mapActions).forEach(key => {
    program
        .command(key)
        .alias(mapActions[key].alias)
        .description(mapActions[key].desc)
        .action(() => {
            if(key === '*'){
                console.log(mapActions[key].desc);
            } else {
                require(path.resolve(__dirname, `./actions/${key}`))(process.argv.splice(3))
            }
        })
})

program.parse(process.argv)
const path = require('path')

const fs = require('fs')
const Inquirer = require('inquirer')
const del = require('del')
const axios = require('axios')
const { promisify }  = require('util')

const downloadGitRepo = promisify(require('download-git-repo'))

const ncp = promisify(require('ncp'))

const shelljs = require('shelljs')

const ora = require('ora')

const baseUrl = 'https://api.github.com'

const existDir = async(projectName) => {
    const dir = path.resolve('.')
    const createDir = dir + '/' + projectName
    if(fs.existsSync(createDir)){
        const result = await Inquirer.prompt({
            name:'create dir',
            type:'confirm',
            message:'Overwrite your existed Directory ?',
            default: true
        })
        
        if(result){
            await del(createDir, { force: true})
            fs.mkdirSync(createDir)
            return createDir
        } else {
            console.log('取消了创建目录,停止创建目录!');
            process.exit(1)
        }
    }
    fs.mkdirSync(createDir)
    return createDir
}

const fetchRepoList = async () => {
    const { data } = await axios.get(`${baseUrl}/users/tomic/repos`)
    
    const repoName = data.map(item => item.name).filter(item => /template/.test(item))
    
    return repoName
}

const fetchRepoTags = async (repo) => {
    const { data } = await axios.get(`${baseUrl}/repos/tomic/${repo}/tags`)
    
    const tagName = data.map(item => item.name)
    
    return tagName
}

const waitLoading = async (fn, message) => {
    const spinner = ora(message)
    spinner.start()
    const result = await fn()
    spinner.succeed()
    return result
}

module.exports = async (projectName) => {
    //创建目录,如果存在,提示用户是否覆盖
    const desk = await existDir(projectName)
    console.log(desk);
    //拉取github template 选择指定的tag与仓库
    const  repos = await waitLoading(fetchRepoList,'获取远程仓库列表!')
    const { repo } = await Inquirer.prompt({
        name:'repo',
        type:'list',
        message:'Choose the repo needs to download!',
        choices: repos
    })
    const tags = await fetchRepoTags(repo)
    const { tag } = await Inquirer.prompt({
        name:'tag',
        type:'list',
        message:'Choose the tag needs to download!',
        choices: tags,
    })
    //下载并安装依赖
    let repoUrl = `terry/${repo}`
    if(tag){
        repoUrl = `terry/${repo}#${tag}`
    }
    downloadGitRepo(repoUrl,desk + '/tmp')
    
    await ncp(desk + '/tmp',desk)
    
    await del(desk + '/tmp')
    
    shelljs.cd(desk)
    
    shelljs.exec('npm install')
    
}

 

posted @ 2020-09-18 17:23  广广-t  阅读(173)  评论(0)    收藏  举报