Thought analysis

We can think of a code generator as gathering some information and rendering it into a fixed code template to generate the final code

Prepare knowledge

From the above analysis, we know that to write a code generator we need to know the following things:

  1. You can get user input
  2. You can obtain database information
  3. Memory information can be written to a local file

Almost all popular programming languages can do this. We chose to use nodeJs Express here

ejs mysql

Key step code

  1. Install the Express application generator

    #If the installation is slow please use CNPM https://www.oschina.net/p/cnpm?hmsr=aladdin1e1
    npm install -g express-generator
    
    #Later versions of Node (included in Node.js 8.2.0 and later) can be installed using the following command
    npx express-generator
    Copy the code
  2. Generate the Express basic framework

    #Generate project folder
    mkdir gen
    cd gen
    
    #Generating the Express Framework
    express -e --git
    Copy the code
  3. Installing dependency packages

    Lodash is a common JavaScript toolkit
    npm install --save lodash mysql
    Copy the code
  4. Create a basic information collection form

    Open the Express project folder generated by the previous command and open the app.js file in the root directory of the project

    // Around 12-14 of the code
    // view engine setup
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine'.'ejs');
    Copy the code

    Ejs template directory is the views folder in the project root directory. Add a form to index.ejs as follows

    <! DOCTYPEhtml>
    <html>
    
    <head>
        <title>Quick clustering code generator</title>
        <link rel='stylesheet' href='/ lib/bootstrap 4.6.0 / CSS/bootstrap. Min. CSS'/>
        <link rel='stylesheet' href='/stylesheets/style.css'/>
    </head>
    
    <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="#">Quick clustering code generator</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
                aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item active">
                    <a class="nav-link" href="#">The generated code<span class="sr-only">(current)</span></a>
                </li>
            </ul>
        </div>
    </nav>
    
        <div class="row" style="margin:30px auto; width:600px ">
            <form action="/tables" method="post">
                <div class="form-group">
                    <label for="exampleInputEmail1">The project name</label>
                    <input type="name" class="form-control">
                </div>
                <div class="form-group">
                    <label for="exampleInputPassword1">The author</label>
                    <input class="form-control" name="author">
                </div>
                <div class="form-group">
                    <label for="exampleInputPassword1">Table prefix Removal</label>
                    <input class="form-control" name="pre">
                </div>
                <div class="form-group">
                    <label for="exampleInputPassword1">Generate the file</label>
                    <br/>
                    <span>The backend:</span>
                    <label><input type="checkbox" name="files[]" value="mappper">mappper</label>
                    <label><input type="checkbox" name="files[]" value="mappperXML">mappperXML</label>
                    <label><input type="checkbox" name="files[]" value="entity">entity</label>
                    <label><input type="checkbox" name="files[]" value="param">param</label>
                    <label><input type="checkbox" name="files[]" value="result">result</label>
                    <label><input type="checkbox" name="files[]" value="controller">controller</label>
                    <label><input type="checkbox" name="files[]" value="service">service</label>
                    <label><input type="checkbox" name="files[]" value="serviceimpl">serviceimpl</label>
                    <label><input type="checkbox" name="files[]" value="enum">enum</label>
                    <br/>
                    <span>Front end:</span>
                    <label><input type="checkbox" name="files[]" value="indexJsx">indexJsx</label>
                    <label><input type="checkbox" name="files[]" value="addJsx">addJsx</label>
                    <label><input type="checkbox" name="files[]" value="editJsx">editJsx</label>
                    <label><input type="checkbox" name="files[]" value="apiJs">apiJs</label>
                </div>
                <div class="form-group">
                    <label for="exampleInputPassword1">Whether to generate API documentation</label>
                    <br/>
                    <label><input type="radio" name="api">is</label>
                    <label><input type="radio" name="api">no</label>
                </div>
                <button type="submit" class="btn btn-primary">The next step</button>
            </form>
        </div>
    </body>
    
    </html>
    
    Copy the code
  5. Create a route for receiving form information

    The Express route file is written in the routes folder under the root of the project. We added a new route to routes/index.js to receive form information

    Express Basic Routing

    router.post('/tables'.function (req, res) {
       // req requests objects for data
    });
    
    Copy the code
  6. Create a database connection pool

    After we get the information submitted by the user we also need to get the information in the database.

    #Create a configuration folder under the project root directory to store configuration files
    mkdir config
    Copy the code

    Create a db.js file in the config folder to configure database information and create a database connection pool

    var mysql = require('mysql')
    var pool = mysql.createPool({
        connectionLimit: 10.host: '127.0.0.1'.user: 'root'.password: ' '.database: 'database'
    });
    
    function  query(sql, values, callback) {
        console.log("db pool");
        pool.getConnection(function (err, connection) {
            if(err) throw err;
            console.log("sql ",sql,values);
            //Use the connection
            connection.query(sql, values,function (err, results, fields) {
                console.log(JSON.stringify(results),err);
                // Every query is called back
                callback(err, results);
                // Just release the link in the buffer pool, not destroyed
                connection.release();
                if(err) throw error;
            });
    
        });
    }
    
    exports.query = query;
    Copy the code
  7. Gets information about all tables in the specified library

    With the database connection pool created above to read information from the database, we return to the routes/index.js file

    // Import the database
    const db = require(".. /config/db").../** * get all data from the database */
    router.post('/tables'.function (req, res) {
        /** * 1. Get the information submitted in the previous step from req.body. Query the database to get the current connected database table information */
        db.query("show tables"[],function (err, rows) {
            res.render('index', {
                postData: {... req.body}, tables }); }); });Copy the code
  8. Gets information about all fields in the specified table

    In the same way, we can create a new route to get all the fields in the specified table

    /** * returns table structure information by table name */
    router.get('/table_info'.function (req, res) {
        db.query('show full fields from' + req.query.name, [], function (err, rows) {
            res.send(rows);
        });
    });
    Copy the code
  9. Summary database information and form information rendered to the template

    router.post('/gen'.function (req, res) {
    
        // let dir = tempRootPath + new Date().getTime() + "/"
        let dir = tempRootPath
        const {tableColumn, postData} = req.body
    
        // Loop through all tables
        _.each(tableColumn, function (item, key) {
            // The name of the PASCAL table
            let pskTableName = _.capitalize(key)
    
            let frontPath = dir + key + "/front/" + pskTableName + "/"
            // Generate the front end of the component according to the table name in PASCAL mode
            mkdirsSync(frontPath)
    
            // Use a direct structure to avoid bugs
            const {author, pre} = postData
            /* * Configure the template according to the file structure to generate the corresponding data */
            let allColumns = tableColumn[key] ? tableColumn[key] : []
    
            // Generate code
            generate(frontTemplateFiles, frontPath, {
                updateColumns: _.filter(allColumns, item= > item.showUpdate),
                updateMustColumns: _.filter(allColumns, item= > item.mustUpdate),
                addColumns: _.filter(allColumns, item= > item.showAdd),
                addMustColumns: _.filter(allColumns, item= > item.mustAdd),
                listColumns: _.filter(allColumns, item= > item.showList),
                searchColumns: _.filter(allColumns, item= > item.isSearch),
                allColumns,
                author,
                pre,
                pskTableName
            })
        })
    
    
        res.send("ok")})Copy the code

The code address

Making the address