Make writing a habit together! This is the 7th day of my participation in the “Gold Digging Day New Plan ยท April More text Challenge”. Click here for more details.
What will be gained
- Master command line interaction methods
- Server framework
egg.js
The application andapi
Development methods egg.js
Integrated cloudmongodb
Implementing data storage
The main content
- Scaffolding project creates functional architecture design
- Obtain basic project information through command line interaction
egg.js
+ cloudmongodb
The integration of- Develop front-end project templates
egg.js
Get the project templateAPI
The development of- Project template download function development
inquirer
Source code parsing, thoroughly understand command line interaction
Create functional architecture designs
- Scalable: can quickly reuse to different teams, adapt to the differences between different teams
- Low cost: Templates can be added without changing the scaffolding source code, and the cost of adding templates is very low
- A high performance: Controls storage space and makes full use of it during installation
node
Multiple processes improve installation performance
Create functional architecture blueprints
Preparation stage
Template Download phase
Template Installation Phase
Preparatory development
// commands\init\lib\index.js
'use strict';
const fs = require('fs');
const Command = require('@hzw-cli-dev/command');
const log = require('@hzw-cli-dev/log');
const inquirer = require('inquirer');
const fse = require('fs-extra');
const semver = require('semver');
const TYPE_PROJECT = 'project';
const TYPE_COMPONENT = 'component';
/ * * *@description: init Command, inherited from Command *@param {*}
* @return {*}* /
class InitCommand extends Command {
/ * * *@description: Command initialization phase *@param {*}
* @return {*}* /
init() {
// Project name
this.projectName = this._argv[0] | |'project';
// Whether to carry the force parameter
this.force = !!this._argv[1].force;
log.verbose('๐๐ ~ Mandatory Installation '.this.force);
log.verbose('๐๐ ~ Project name '.this.projectName);
}
/ * * *@description: Command execution phase *@param {*}
* @return {*}* /
async exec() {
try {
// 1. Preparation stage
const ret = await this.prepare();
if (ret) {
// 2. Download the template
// 3. Install the template}}catch(error) { log.error(error.message); }}/ * * *@description: Preparation stage *@param {*}
* @return {*}* /
async prepare() {
Path.resolve ('.') is also available
const localPath = process.cwd();
// 1. Check whether the current directory is empty
const isEmpty = this.isDirEmpty(localPath);
let isContinue = false;
if(! isEmpty) {if (!this.force) {
// Ask the user to continue
const res = await inquirer.prompt([
{
type: 'confirm'.name: 'isContinue'.message: 'The current folder is not empty. Do you want to continue creating the project here? '.default: false,}]); isContinue = res.isContinue;if(! isContinue) {return false; }}// 2. Determine whether to enable forcible installation
// Empty the folder for creation
if (isContinue || this.force) {
const { isDelete } = await inquirer.prompt([
{
type: 'confirm'.name: 'isDelete'.message: 'Do you want to clear the files in the current directory? '.default: false,}]);if (isDelete) {
// Clear the current directoryfse.emptyDirSync(localPath); }}}// 3. Select create project or component
// 4. Get basic information about the project
return this.getInfo();
}
/ * * *@description: Select create project or component to get basic information about the project return Object *@param {*}
* @return {*} Basic project information */
async getInfo() {
const info = {};
// Select create project or component;
const { type } = await inquirer.prompt({
type: 'list'.message: 'Please select an initialization type'.name: 'type'.default: TYPE_PROJECT,
choices: [{name: 'the project'.value: TYPE_PROJECT,
},
{
name: 'components'.value: TYPE_COMPONENT,
},
],
});
log.verbose('type', type);
// Get basic information about the project;
if (type === TYPE_COMPONENT) {
}
if (type === TYPE_PROJECT) {
const o = await inquirer.prompt([
{
type: 'input'.message: 'Please enter project name'.name: 'project'.validate: (a) = > {
const reg =
/^[a-zA-Z]+([-][a-zA-Z0-9]|[_][a-zA-Z0-9]|[a-zA-Z0-9])*$/;
if (reg.test(a)) {
return true;
}
return 'Must start with a letter, end with a number or a letter. Only characters allowed are - and _'.; }, {},type: 'input'.message: 'Please enter the project version number'.name: 'version'.default: '1.0.0'.validate: (a) = > {
return!!!!! semver.valid(a) ||'Please enter a valid version number';
},
filter: (a) = > {
if(!!!!! semver.valid(a)) {return semver.valid(a);
}
returna; }},]);console.log('๐๐ ~ InitCommand ~ o', o);
}
return info;
}
/ * * *@description: Checks whether the current directory is empty *@param {*}
* @return { Boolean } False is not empty */
isDirEmpty(localPath) {
// Read all files in the current directory
let fileList = fs.readdirSync(localPath);
// Filter out unaffected file directories (whitelist)
fileList = fileList.filter(
(file) = >! file.startsWith('. ') && ['node_modules'].indexOf(file) < 0,);// No directory or number of files is 0 returns true
return! fileList || fileList.length ===0; }}/ * * *@description: Returns an instance of InitCommand *@param {*} Argv: projectName projectName, options of the command, commander instance *@return {*}* /
function init(argv) {
return new InitCommand(argv);
}
module.exports = init;
module.exports.InitCommand = InitCommand;
Copy the code