preface

This is not a holiday, while there is time, ready to do a scaffolding play, because node community has been very perfect, just need to step on the shoulders of the giant “building blocks”, we start from three parts, tools — to do good work must first sharp tools; Practice — Practice is the sole criterion for testing truth; Coding– Only hand familiar, ha ha, pull down to play. Trust me start at zero and fuck you when I’m done.

The effect

First above:

(figure 1)

[2][3]

Look familiar? Yes, it’s a copy of vue-CLI. One step at a time. You’ll get it.

Tool post

Learning is a process. Since it is a tool, we should first know what the tool is, what it can do, and how to use it. Here’s a look at what it is, what it can do, and how it can be used: —- Inquirer, Commander, Chalk, shelljs. Of course, there are many tools, choose their familiar, if not familiar, might as well learn to learn. Look at the code and skip to the practice section.

inquirer

If you look at vue-CLI code, it also uses this library. So what is an inquirer? Inquirer is a console interactive JS library. What can be done? As shown above, it can be used for more user-friendly interaction. How do you use it? Take a look. `

Install NPM install InquirerCopy the code
Var inquirer = require('inquirer'); inquirer .prompt([ /* Pass your questions in here */ ]) .then((answers) => { // Use user feedback for... whatever!! }) .catch((error) => { if (error.isTtyError) { // Prompt couldn't be rendered in the current environment } else { // Something else went wrong } });Copy the code
inquirer.prompt(questions: [Question]):Promise
Copy the code
interface Ichoices { name: string, value: string | number | boolean, short? : string }Copy the code
Interface Question {// Interface type: 'input' | 'number' | 'confirm' | 'list' | 'rawlist' | 'expand' | 'checkbox' | 'password' | 'editor'; // The name of the current input, which can be used to get input data. / / hint information message: string | Function; / / to the default values for the default: string | number | Boolean | | [any] Function; / / hint to the user to select data choices: number | string | Ichoices | Function; Validate: Function; Filter: Function; Transformer: Function; / / when something triggered, the when returns true or false: the Function | Boolean; Checkbox, list, rawList, expand pageSize: number; // Change the default prefix to show the default is? prefix: string; // Change the default suffix to show the default is empty string suffix: string; // If the answer already exists, the question is forced. // Whether to loop when selecting a list default true loop: Boolean; }Copy the code

Prompt receives an array of questions, each of which is the type defined above. As an example, look at the corresponding code in Figure 1:

[4]

Type is confirm. You need to enter Y /N. The default value is true. Subsequent executions are performed based on the previous results.

npm

github

commander

What is Commander? It is a complete NodeJS command-line solution. What can be done? Execute custom commands, such as MCLI create

used in this article to create a project. Here’s how to use it:

NPM Install CommanderCopy the code
Use const {program} = require('commander'); program .option('-d, --debug', 'output extra debugging') .option('-s, --small [type]', 'small pizza size', 'large') .option('-p, --pizza-type <type>', 'flavour of pizza', 'pizza'); program.parse(process.argv); const options = program.opts(); if (options.debug) console.log(options); console.log('pizza details:'); if (options.small) console.log('- small pizza size'); if (options.pizzaType) console.log(`- ${options.pizzaType}`);Copy the code

Node -r ts-node/register SRC /index.ts

[5]

node -r ts-node/register src/index.ts -d

[6]

When executing the first command, the default value is printed because both the -s and -p options have default values. [type] and

indicate optional and mandatory respectively. If the -p option is executed, the type value must be passed or an error will be reported. Execute -s without passing to use the default value. Properties that do not need to be passed are Boolean types, and values that need to be passed are the data being passed. And then according to the user to execute the option procedures to do the next step.

Here’s another command:

.command() can execute a command, such as.command(‘create

‘). See if create feels familiar again, that’s the create that generated the project.

indicates that executing the command must pass name, our project.

npm

github

chalk

What is Chalk? I’m sure you’ve all used it. But there are unavoidably unused, we also briefly introduced here. It is a coloring library that colors the data presented to the user. Note: Version 5 is the ESM. If you want to use it in TS or build tools, version 4 is recommended

Install YARN add [email protected]Copy the code
Const chalk = require('chalk'); console.log(chalk.blue('Hello world! '));Copy the code

API and other official website description is very detailed, a look will have a feeling of writing CSS you.

npm

shelljs

Shell, it goes without saying that ShellJS is a portable (Windows/Linux/macOS) implementation of Unix shell commands based on node.js API. This makes it easy to execute shell scripts. How do you use it?

Install NPM install ShelljsCopy the code
Var shell = require('shelljs'); if (! shell.which('git')) { shell.echo('Sorry, this script requires git'); shell.exit(1); } // Copy files to release dir shell.rm('-rf', 'out/Release'); shell.cp('-R', 'stuff/', 'out/Release'); // Replace macros in each .js file shell.cd('lib'); Shell. Ls (' *. Js). ForEach (function (file) {shell. Sed (' -i ', 'BUILD_VERSION', 'v0.1.2' file). shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file); shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file); }); shell.cd('.. '); // Run external tool synchronously if (shell.exec('git commit -am "Auto-commit"').code ! == 0) { shell.echo('Error: Git commit failed'); shell.exit(1); }Copy the code

With shellJS, the script execution problem is solved. At this point, the tools needed for a CLI are understood, and the skeleton of an imaginary CLI is formed.

github

practice

The code is too long to post. I’ll stick it up

#! /usr/bin/env node const inquirer = require('inquirer'); const chalk = require('chalk'); const program = require('commander'); const readline = require('readline'); const shell = require('shelljs'); // type choices = number | string | {name: string, value: string | number | boolean, short? : string} | Function; Const optionFunc = (newVal, preValue) => {console.log(newVal, preValue); } program. configureOutput({// here to make it easy to tell writeOut: (STR) => process.stdout.write(' [OUT] ${STR} '), writeErr: (STR) => process.stdout.write(' [ERR] ${STR} '), // Highlight error outputError: (str, Write) = > write (chalk. Hex (' # f40) (STR))}) command (' create < name > '). The description (' create application '). Option (' - f -- force < path > ', Action ((name, options, command) => {console.log(name, 'xx') if (! Name) {console.log(chalk. Hex ('#f40')(' please input project name ')) return; } else { inquirer.prompt([ { type: 'confirm', name: 'update', message: `Your connection to the default yarn registry seems to be slow.\n Use https://registry.npm.taobao.org for faster installation?`, default: true, }, { when: (answer) = > {if! Answer. (update) {the console. The log (chalk. Hex (' # f40) (' to start the update... '));}}}, {type: 'list', name: 'preset', message: 'Please pick a preset:', choices: [ { name: 'Default ([Vue 2] babel, eslint)', value: '1', }, { name: 'Default (Vue 3) ([Vue 3] babel, eslint)', value: '2', }, { name: 'Manually select features', value: '3', }, ], when: (answer) => {if (answer.update) {console.log(chalk. Red (' \n\nVue CLI v4.5.13 ')); The console. The log (` ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ │ New version available at ${chalk. Hex (' # f40) (' 4.5.13 ')} - > ${chalk. Hex (' # f40) (' 4.5.15 ')} │ │ Run ${chalk. Hex (' # f40) (' NPM I - g @ vue/cli ')} to update! │ │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ `);} return answer. Update;}}, {type: 'list', name: 'type', message: 'Pick the package manager to use when installing dependencies:', choices: [ { name: 'Use Yarn', value: 'yarn', }, { name: 'Use NPM', value: 'npm', }, ], when: (answer) => { return answer.update } }, { when: (answer) = > {the if (answer. Type) {the console. The log (chalk. Hex (' # f40) (' Vue CLI v4.5.13 ')); The console. The log (chalk. Hex (' # f40) (' ✨ Creating project in/Users/zhiepngwan/Desktop/demo / 1111. ')); The console. The log (chalk. Hex (' # f40) (' 🗃 Initializing the git repository... ')); Console. log(chalk. Hex ('#f40')('⚙️ Installing CLI plugins. This might take a while...');}}}, {type: 'Confirm ', name: 'join', message: 'join me ', default: true, when: (answer) => {return answer.update}}, {when: (answer) => { if (! Answer.join) {const outStream = process.stdout; // createInterface const rl = readline.createinterface ({input: process.stdin, output: OutStream}); const textArr = ['2021', 'quit ', '2022',' Welcome ', 'New Year ', 'Fight', 'Together! // const randomPos = () => {const x = math.floor (30 * math.random ());  const y = Math.floor(10 * Math.random()); return [x, y]; } // chalk color const randomTextStyle = (text) => {const styles = ['redBright', 'yellowBright', 'blueBright', 'cyanBright', 'greenBright', 'magentaBright', 'whiteBright'];  const color = styles[Math.floor(Math.random() * styles.length)]; return chalk[color](text); } // Const delay = (time) => {return new Promise(resolve) => setTimeout(resolve, time));  } setTimeout( async () => { for(let i = 0; i < textArr.length; i++) { readline.cursorTo(outStream, ...randomPos()); Readline.cursorto (outStream, 0, 0); rl.write(randomTextStyle(textArr[I]));  readline.clearScreenDown(outStream); } }, 1000); } } } ]) .then((answer) => { if (! answer.join) { readline.cursorTo(process.stdout, 0, 0); Readline.clearscreendown (process.stdout); readScreenDown (process.stdout); // Clear the screen as seen using vue-cli return; } console.log(answer); console.log('etx... And then a series of commands '); // if (shell.exec('yarn add jQuery').code! == 0) { // shell.echo('Error: install failed'); // shell.exit(1); // } // if (shell.exec('git clone https://github.com/wanzhip/mcli.git').code ! == 0) { // shell.echo('Error: install failed'); // shell.exit(1); / /}}); }; }); program.parse(process.argv);Copy the code

Coding

Only the hand is familiar, tap to deepen memory. The full code will be posted to Github later. Happy New Year to you all!! New Year new atmosphere! Bonanza! Step up!

The appendix

zhuanlan.zhihu.com/p/452195702

www.wmm20.com/posts/8e3b1…

Juejin. Cn/post / 684490…

Juejin. Cn/post / 702032…

Juejin. Cn/post / 686643…