preface

The scaffolding tool vue has vue-cli and react has create-react-app, which generates new project templates based on options. But often these customized enough, after generating project will need to add a lot of configuration, from the generation, there is still a gap, which can be treated by customizing their own cli tool, do a simple cli tools, integrated their default template, according to the template to generate, follow-up can add and update the maintenance of the template.

package.json

As a CLI tool, you need to be able to execute commands on the command line, so you need to declare in package.json. The main field is bin, and the executable file is declared as follows: GDPG is an executable command, and SRC /index.js is executed

"bin": {
  "gdpg": "src/index.js"
},
Copy the code

Executable file

SRC /index.js to indicate an executable file

#! /usr/bin/env node
Copy the code

This section describes cli related tool libraries

commander

The main function of commander is to take parameters on the command line, for example

gdpg init -l 
# or
gdpg init --local
Copy the code

The code is as follows: GDPG -v or GDPG –version will print the current VERSION of the CLI. Add parameters can be defined by the accepted parameters to achieve the corresponding function

program
    .version(pkg.version, '-v, --version')
    .usage('<command> [options]')
    .description('Standard tooling generate dir from templates')

program
    .command('init [name]')
    .description('Create a project')
    .option('-l, --local'.'Create dir from local template')
    .option('-g, --git'.'Create dir from git address')
    .action((name, options) = > {
        console.log(name, options.local, options.git)
    })
Copy the code

inquirer

Inquirer: input, number, confirm, yes, no, list, rawlist, expand, checkbox, password, password Editor launches an instance of the user’s preferred editor on a temporary file.

type: (String) Type of the prompt. Defaults: input – Possible values: input, number, confirm, list, rawlist, expand, checkbox, password, editor

Ask the user’s choice, perform different operations according to the user’s choice, generate different templates

ora

Equivalent to the progress bar in the command line terminal, used to indicate the start and end of the action, load medium state

chalk

Chalk, or chalk, outputs colored text in a command line terminal

download-git-repo

Download and extract a Git repository (GitHub, GitLab, Bitbucket) from a node

update-notifier

Update notification procedures, toolkits have updated words prompt

const updateNotifier = require('update-notifier');
const pkg = require('./package.json');

updateNotifier({pkg}).notify();
Copy the code

GDPG – CLI function example

Several recent initialization default templates are available. Eslint, prettier, Husky, CommitLint, Vue -router/react-router-dom, Axios, and many more are already preset

The directory structure

GDPG - cli ├ ─ ─ LICENSE ├ ─ ─ the README. Md ├ ─ ─ dir. Md ├ ─ ─ example. The PNG ├ ─ ─ generators │ ├ ─ ─ react17 │ ├ ─ ─ vue2 │ ├ ─ ─ vue3 │ ├ ─ ─ │ ├─ ├─ ├─ download.txt │ ├─ download.txt │ ├─ download.txt │ ├─ download.txt │ ├─ download.txt │ ├─ download.txt │ ├─ download.txtCopy the code

package.json

{
  "name": "gdpg-cli"."version": "1.0.0"."license": "MIT"."main": "lib/index.js"."bin": {
    "gpdg": "lib/index.js"
  },
  "files": [
    "lib"]."dependencies": {
    "chalk": "^ 4.4.1"."commander": "^ 7.2.0"."download-git-repo": "^ 3.0.2." "."fs-extra": "^ 10.0.0"."inquirer": "^ 7.3.3." "."log-symbols": "^ 2.2.0." "."ora": "^ 5.4.0"."update-notifier": "^ 5.1.0"
  },
  "scripts": {
    "lint": "eslint --fix"."prettier": "prettier --write lib"."release": "standard-version"
  },
  "devDependencies": {
    "@commitlint/cli": "^ 12.1.1." "."@commitlint/config-conventional": "^ 12.1.1." "."eslint": "^ 7.26.0"."eslint-config-prettier": "^ 8.3.0"."eslint-plugin-prettier": "^ 3.4.0"."husky": "^ 4.3.7"."lint-staged": "^ 10.5.3"."prettier": "^ 2.3.0." "."standard-version": "^ 9.3.0"
  },
  "engines": {
    "node": "> = 10.12"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"."commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"}},"commitlint": {
    "extends": [
      "@commitlint/config-conventional"]},"lint-staged": {
    "*.{js}": [
      "prettier --write"."eslint --fix"."git add"]}}Copy the code

lib/generator.js

const inquirer = require('inquirer')
const fsExtra = require('fs-extra')
const download = require('download-git-repo')
const ora = require('ora')
const log = require('./log')
// const path = require('path')

/** * Three options: 1. Default 2. Download from git 3. Clone * gdpgGenerator select templates from presets * gitGenerator downloads templates from Git * localGenerator downloads templates from local */

/ * * *@param {*} Prompt query option *@param {*} Action Executes the function */ after the query
const generator = (prompt, action) = > {
    inquirer
        .prompt(prompt)
        .then((answers) = > {
            action(answers)
        })
        .catch((error) = > {
            if (error.isTtyError) {
                log.error(`Prompt couldn't be rendered in the current environment`)}else {
                log.error(error)
            }
        })
}

const spinner = ora('Download from template... ')

const successInfo = (name) = > {
    spinner.succeed()
    console.log(
        ` ▄ █ █ █ █ ▓ █ █ █ █ █ ▄ █ █ ▓ █ █ █ ▄ █ █ █ █ ▄ █ █ █ █ ▄ █ █ ▓ █ █ ▓ █ █ ▒ ▀ █ ▒ ▒ █ █ ▀ █ █ ▌ ▓ █ █ ░ █ █ ▒ █ █ ▒ ▀ █ ▒ ▒ █ █ ▀ ▀ █ ▓ █ █ ▒ ▓ █ █ ▒ ▒ █ █ ░ ▄ ▄ ▄ ░ ░ █ █ █ ▌ ▓ █ █ ░ █ █ ▓ ▒ ▒ █ █ ░ ▄ ▄ ▄ ░ ▒ ▓ █ ▄ ▒ █ █ ░ ▒ █ █ ▒ ░ ▓ █ █ █ ▓ ░ ▓ █ ▄ ▌ ▒ █ █ ▄ █ ▓ ▒ ▒ ░ ▓ █ █ █ ▓ ▒ ▓ ▓ ▄ ▄ █ █ ▒ ▒ █ █ ░ ░ █ █ ░ ░ ▒ ▓ █ █ █ ▀ ▒ ░ ▒ █ █ █ █ ▓ ▒ █ █ ▒ ░ ░ ░ ▒ ▓ █ █ █ ▀ ▒ ▒ ▓ █ █ █ ▀ ░ ░ █ █ █ █ █ █ ▒ ░ █ █ ░ ░ ▒ ▒ ▒ ▒ ▓ ▒ ▒ ▓ ▒ ░ ░ ░ ░ ▒ ▒ ░ ░ ▒ ▒ ░ ░ ▒ ░ ▓ ░ ░ ▓ ░ ░ ░ ▒ ▒ ░ ▒ ░ ░ ░ ░ ▒ ░ ░ ▒ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ▒ I did not do that myself
    )
    log.success(` 🎉 Successfully created the project${name}. `)
    log.success('👉 Get started with the following commands:\n')
    log.bash(`cd ${name}`)
    log.bash(`yarn install`)}const GDPG_PROMPTS = [{
    name: 'version'.message: 'Select version'.type: 'list'.choices: [{
            name: 'Vue 2 + Javascript + Less'.value: 'vue2'
        },
        {
            name: 'Vue 3 + Javascript + Less'.value: 'vue3'
        },
        {
            name: 'Vue 3 + Typescript + Sass + ElementPlus'.value: 'vue3_ts'
        },
        {
            name: 'Vue 3 + Typescript + Sass + ElementPlus + Vite'.value: 'vue3_vite'
        },
        {
            name: 'React 17 + Javascript + Less + Antd'.value: 'react17'}}]]const downLoadUrl = 'direct:https://github.com/xxx/gdpg-cli/archive/refs/heads/master.zip'

const downLoadFromZip = (dir, name) = > {
    download(downLoadUrl, name, {
        map: file= > {
            file.path = file.path.replace(`generators/${dir}/ `.' ')
            return file;
        },
        filter: file= > {
            return file.path.indexOf(`generators/${dir}/ `) > -1}},(err) = > {
        if (err) {
            spinner.fail()
            log.error(err)
        } else {
            successInfo(name)
        }
    })
}

const gdpgGenerator = (name) = > {
    generator(GDPG_PROMPTS, (answers) = > {
        spinner.start()
        downLoadFromZip(answers.version, name)
    })
}

const GIT_PROMPTS = [{
    name: 'version'.message: 'Enter git address'.type: 'input'.name: 'git'
}]

const gitGenerator = (name) = > {
    generator(GIT_PROMPTS, (answers) = > {
        spinner.start()
        download(`direct:${answers.git.trim()}`, name, {
            clone: true
        }, (err) = > {
            if (err) {
                spinner.fail()
                log.error(err)
            } else {
                successInfo(name)
            }
        })
    })
}

const LOCAL_PROMPTS = [{
    name: 'version'.message: 'Enter local address'.type: 'input'.name: 'path'
}]

const localGenerator = (name) = > {
    generator(LOCAL_PROMPTS, (answers) = > {
        spinner.start()
        fsExtra.copy(answers.path.trim(), `. /${name}`.(err) = > {
            if (err) {
                spinner.fail()
                log.error(err)
                return
            }
            successInfo(name)
        })
    })
}

module.exports = {
    gdpgGenerator,
    gitGenerator,
    localGenerator
}
Copy the code

lib/index.js

#! /usr/bin/env node
const program = require('commander')
const pkg = require('.. /package.json')
const updateNotifier = require('update-notifier')
const log = require('./log')
const fs = require('fs')
updateNotifier({ pkg }).notify({ isGlobal: true })
const { gdpgGenerator, gitGenerator, localGenerator } = require('./generator')

/** * program asks for help. If no arguments are entered, the help view command */ is output

program
    .version(pkg.version, '-v, --version')
    .usage('<command> [options]')
    .description('Standard tooling generate dir from templates')

program
    .command('init [name]')
    .description('Create a project')
    .option('-l, --local'.'Create dir from local template')
    .option('-g, --git'.'Create dir from git address')
    .action((name, options) = > {
        if(! name)return log.error('Please input your project name')
        // Check whether the local directory already exists
        if (fs.existsSync(name)) return log.error('Project name already exist')
        if (options.git) {
            gitGenerator(name)
        } else if (options.local) {
            localGenerator(name)
        } else {
            gdpgGenerator(name)
        }
    })

program.parse(process.argv)

const commandName = program.args.length
if(! commandName) { program.help() }Copy the code

lib/log.js

const chalk = require('chalk')
const logSymbols = require('log-symbols')

module.exports = {
    success: (text) = > console.log(logSymbols.success, chalk.green(text)),
    info: (text) = > console.log(logSymbols.info, chalk.blue(text)),
    bash: (text) = > console.log(chalk.cyan(` $${text}`)),
    warning: (text) = > console.log(logSymbols.warning, chalk.yellow(text)),
    error: (text) = > console.log(logSymbols.error, chalk.red(text))
}
Copy the code

The installation

npm i -g gdpg-cli
# or
yarn global add gdpg-cli
Copy the code

Check the version

gdpg -v
# or 
gdpg --version
Copy the code

See the help

gdpg -h
# or 
gdpg --help
Copy the code

1. Pull the build project from the default template

gdpg init <project-name>
Copy the code

2. Download the template from Git to build the project

gdpg init -g <project-name>
# or
gdpg init --git <project-name>
Copy the code

3. Download the generated project from the local folder

gdpg init -l <project-name>
# or
gdpg init --local <project-name>
Copy the code