Nodejs uses readline to prompt for content input example code

Nodejs uses readline to prompt for content input example code

Preface

Recently, I forgot to change the version number when testing a small version. Then I thought of prompting for the version number before packaging, and then entering the version number into the version description. The final effect is that double-clicking the bat file will prompt you to enter the version number in the terminal, and the version number will be saved after entering.

Although batch processing can also do this, it is more convenient to write it in js, so js is chosen for processing.

The process is divided into four steps

  • bat execute js
  • The terminal prompts you to enter the version number and execute the packaging command
  • Modify the version number file
  • gulp reads the version number json file

Simply put, use bat file to trigger the packaging command for packaging.

1. bat executes js

First create two files buildVersion.bat and buildVersion.js.

Use node to run js file in buildVersion.bat

@echo off
set curpath=%~dp0
%curpath%nodejs\node.exe %curpath%buildVersion.js
pause

%~dp0 is the current directory. You can also pass parameters after js, such as --buildType default

2. The terminal prompts you to enter the version number and execute the packaging command

Use readline to achieve the question-and-answer effect, and then use child_process to execute the packaged command line.

Enter the buildVersion.js file and write a simple prompt input effect first.

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});
rl.question(`Please enter the new version number: `, (name) => {

});

This will not achieve the desired effect. We first display the previous version number, then prompt for a new version number, and if the input is empty, the previous version number is used.

// Get version information, which is implemented in the third step var versionInfo;
const versionInfoUrl = './src/config/version/version.js';
function getVersion() {
    var buildVersion = "";
    try {
        versionInfo = require(versionInfoUrl);
        buildVersion = versionInfo.version;
    } catch (error) {

    }
    return buildVersion;
}

The prompt input becomes like this

const chalk = require('chalk'); // Import color library rl.question(`${chalk.cyan("Current version number: ")}${chalk.bold.red(getVersion())} \nPlease enter the new version number: `, (name) => {
    !name && (name=versionInfo?versionInfo.version:"");
    console.log(`${chalk.cyan("The new version number is: ")}${chalk.bold.yellow(name)}`);

The effect on the terminal is

Sometimes there is a fixed prefix before the version number. We display the prefix when prompting for input, and you can delete it at will.

// Write default value rl.write("Version")

The next step is to run the packaging command. The current project is packaged using gulp. To display gulp's prompt in the terminal, use child_process.spawn

// Parse the parameters passed in by bat operation var minimist = require('minimist');
var argv = minimist(process.argv.slice(2), {
    string: ["name"]
});

const child_process = require('child_process');
rl.question(`${chalk.cyan("Current version number: ")}${chalk.bold.red(getVersion())} \nPlease enter the new version number: `, (name) => {
    !name && (name=versionInfo?versionInfo.version:"");
    console.log(`${chalk.cyan("The new version number is: ")}${chalk.bold.yellow(name)}`);
    //Record the new version number changeVersion(name);
    
    var buildType = argv.buildType || "build" // The command is configured in gulp var gulpCmd = `gulp ${buildType} --buildVersion "${name}" --color --f ${__dirname}/gulpfile.js`;
    console.log(gulpCmd);
    let spawnProcess = child_process.spawn(gulpCmd, [], {
        shell: true
    });
    spawnProcess.stdout.on('data', (data) => {
        console.log(`${data.toString()}`);
    });
    spawnProcess.stderr.on('data', (data) => {
        console.log(`stderror: ${data}`);
    });
    spawnProcess.on('close', (code) => {
        if (code !== 0) {
            console.log(`close: $[code]`);
        }
    });
    spawnProcess.on('exit', (code) => {
        // console.log(`exit: ${code.toString()}`);
        console.log(chalk.bold.yellow("----------------- Completed --------------------"));
    });
});

function changeVersion(params) {
    if (versionInfo && versionInfo.changeVersion) {
        versionInfo.changeVersion(params);
    }
}

The effect on the terminal is

Using other packaging tools can be done like this

let exec = require('child_process').execSync;
exec('vue-cli-service --mode dev build', {
    stdio: 'inherit'
});

3. Modify the version number file

To modify the file, I thought of using fs.writeFile to write the file, but this is good for json format, but it is not convenient for js file processing. So I store the version information separately in a json file. Create two files: version.js and version.json.

var VersionInfoJson;
// Considering that it may be referenced in HTML, a distinction is made if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    getVersionInfo(true);
} else {
    if (typeof define === 'function' && define.amd) {
        getVersionInfo(false);
    } else {
        getVersionInfoLocal();
    }
}

function getVersionInfo(isModule) {
    try {
        VersionInfoJson = require("./version.json");
    } catch (error) {
        VersionInfoJson = {};
    }
    VersionInfoJson.buildTime = getNowFormatDate();
    VersionInfoJson.changeVersion = changeVersion;

    if (isModule) {
        module.exports = VersionInfoJson;
    }else{
        define([], function () {
            return VersionInfoJson;
        });
    }
}

async function getVersionInfoLocal() {
    try {
        VersionInfoJson = await getVersionJson();
    } catch (error) {
        VersionInfoJson = {};
    }
    VersionInfoJson.buildTime = getNowFormatDate();
    window.VersionInfo = VersionInfoJson;
}

function getVersionJson() {
    return new Promise((resolve, reject)=>{
        var request = new XMLHttpRequest();
        request.open("get", "config/version/version.json");
        request.send(null);
        request.onload = function () {
            if (request.status == 200) {
                var json = JSON.parse(request.responseText);
                resolve(json);
            }else{
                var json = {};
                resolve(json);
            }
        }
    });
}

function changeVersion(version) {
    var copyVersion = cloneObj(VersionInfoJson);
    copyVersion.version = version;
    if (copyVersion.hasOwnProperty("changeVersion")) {
        delete copyVersion["changeVersion"]
    }
    // console.log(copyVersion, __dirname, __filename)
    let fs = require('fs');
    fs.writeFile(__dirname + "/version.json", JSON.stringify(copyVersion), (err) => {

    });
}

// 1. Use new obj.constructor () to create an empty object instead of using {} or [], so as to maintain the inheritance of the prototype chain;
// 2. Use obj.hasOwnProperty(key) to determine whether the property comes from the prototype chain, because for..in.. will also traverse the enumerable properties on its prototype chain.
// 3. The above function uses a recursive algorithm. If the function has a name and the name will not change in the future, there is no problem with this definition. But the problem is that the execution of this function is tightly coupled to the function name factorial. To eliminate this tight coupling, use arguments.callee.
function cloneObj(obj) {
    if (obj === null) return null
    if (typeof obj !== 'object') return obj;
    if (obj.constructor === Date) return new Date(obj);
    if (obj.constructor === RegExp) return new RegExp(obj);
    var newObj = new obj.constructor(); //keep the inheritance chain for (var key in obj) {
        if (obj.hasOwnProperty(key)) { //Do not traverse the properties on its prototype chain var val = obj[key];
            newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // Use arguments.callee to decouple from the function name}
    }
    return newObj;
}

function getNowFormatDate() {
    var date = new Date();
    var seperator1 = "-"; // year, month, day interval var seperator2 = ":"; // hour, minute, second interval var month = date.getMonth() + 1;
    var strDate = date.getDate();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;
    }
    var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate +
        " " + date.getHours() + seperator2 + date.getMinutes() +
        seperator2 + date.getSeconds();
    return currentdate;
}

4. gulp reads the version number json file

This step is easy. You can directly reference json.

const versionInfo = require('./src/config/version/version.js');

You can also get the version number from the gulp command.

var minimist = require('minimist');
var argv = minimist(process.argv.slice(2), {
    string: ["name"]
});

console.log(argv.buildVersion)

Take a closer look.

Summarize

This is the end of this article about nodejs using readline to prompt input content. For more related nodejs readline prompt input content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Node.js readline example of reading and writing file contents line by line
  • Node.js uses the readline module to implement input and output
  • Detailed explanation of the use of the readline module of Node.js
  • Node.js API detailed explanation of the readline module usage
  • Use of Node.js readline module and util module

<<:  vmware installation error VMware Workstation failed to start VMware Authorization Service

>>:  A practical record of restoring a MySQL Slave library

Recommend

How to create WeChat games with CocosCreator

Table of contents 1. Download WeChat developer to...

How to use Docker-compose to build an ELK cluster

All the orchestration files and configuration fil...

How to use cc.follow for camera tracking in CocosCreator

Cocos Creator version: 2.3.4 Demo download: https...

Mysql implements three functions for field splicing

When exporting data to operations, it is inevitab...

Detailed explanation of commonly used nginx rewrite rules

This article provides some commonly used rewrite ...

Detailed tutorial on installation and configuration of nginx under Centos7

Note: The basic directory path for software insta...

The implementation process of long pressing to identify QR code in WeChat applet

Preface We all know that the QR codes in official...

Sample code for CSS image animation effects (photo frame)

This article introduces the sample code of CSS pi...

An article to understand the advanced features of K8S

Table of contents K8S Advanced Features Advanced ...

javascript input image upload and preview, FileReader preview image

FileReader is an important API for front-end file...

How to configure the Runner container in Docker

1. Create a runner container mk@mk-pc:~/Desktop$ ...

Difference between querySelector and getElementById methods in JS

Table of contents 1. Overview 1.1 Usage of queryS...

MySQL query optimization using custom variables

Table of contents Optimizing sorting queries Avoi...

Detailed explanation of the processing of the three Docker Nginx Logs

Because colleagues in the company need Nginx log ...