Koa scaffolding

I made a KOA scaffolding, koA and mongodb combination, has uploaded GitHub. 👏 👏 👏 👏

portal

(Where the code is written)

To write the code, just add the route fill controller, as shown

The following analysis of what constitutes 👇

koa

const Koa = require('koa');
const app = new Koa();

// response
app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(3000);
Copy the code

See nguyen Yifeng koA framework for more

router

The official example

var Koa = require('koa');
var Router = require('koa-router');

var app = new Koa();
var router = new Router();

router.get('/', (ctx, next) => {
  // ctx.router available
});

app
  .use(router.routes())
  .use(router.allowedMethods());
Copy the code

Practical example

// routers/index.js

const Router = require('koa-router')
const Controllers = require('./controller')({})

const dateNumberController = Controllers('date_number')

const router = new Router({
	prefix: '/api'
})

router
.post(dateNumberController.getPath('add'), dateNumberController.add)
.get(dateNumberController.getPath(`select`), dateNumberController.find)
.post(dateNumberController.getPath(`remove`), dateNumberController.delect)
.post(dateNumberController.getPath(`update`), dateNumberController.update)

module.exports = router

// routers/controller.js
const controllerFunction = ({basePath = '.. /controllers/', router_path_function}) => (controllerName) => {
    const divController = require([basePath, controllerName].join(' '))
    const prefix = controllerName
    class Controller extends divController {
        prefix = ' '
        getPath(name){
            return router_path_function ? router_path_function(this.prefix, name) : `/${this.prefix}/${name}`
        }
    }
    const controller = new Controller()
    controller.prefix = prefix
    returnController} module. Exports = controllers/ / controllers/ controllerFunction // controllers/date_number.js const router = require('./routers')
app.use(router.routes());
Copy the code

See koA-Router Github for more details

bodyparser

We have the route, but we also need the parameters passed from the front end, so we need to get the parameters first

example

app.use(async ctx => {
  ctx.body = ctx.request.body;
});
Copy the code

Post requests are then parsed, either application/ JSON or Application/X-www-form-urlencoded

The effect

Update details at BodyParser GitHub

koa-parameter

Once we get the parameters we need to verify them

// main.js
const parameter = require("koa-parameter")
const error = require("koa-json-error") app.use(parameter(app)); Use (error({postFormat: (e, {stack,... Rest}) => ({stack, rest})})) // in CTX, such as in route ctx.verifyParams({date: {type: "string", required: true },
    list: { type: "array", required: true}})Copy the code

mongodb

With the parameters in hand, the next step is to manipulate the data

basis

Initialize the

Install mongodb, then NPM install Mongoose, and initialize as follows

const mongoose = require('mongoose'// DB_ADDRESS = const DB_ADDRESS ="mongodb://localhost:27017/db"
mongoose.connect(DB_ADDRESS, {useNewUrlParser: true, useUnifiedTopology: true}, err => {
    if (err) {
        log.fatal({msg: '[Mongoose] database connect failed! ', err})
    } else {
        console.log('[Mongoose] database connect success! ')
    }
})
module.exports = mongoose
Copy the code

Build a model

To use it, we need to create a set first (called a table in mysql), but MD is more flexible and can operate directly in the code, we need to create the model first.

const mongoose = require('mongoose'); const { Schema, model } = mongoose; // Data modellet DateNumberSchema = new Schema({
    date: { type: String, required: true, unique: true },
    list: { type: Array, require: true}}); module.exports = model('DateNumber', DateNumberSchema);
Copy the code

Operating database

check

const data = await DateNumber.find()
Copy the code

new

Const data = await to(new DateNumber({date, list}).save()Copy the code

delete

const data = await DateNumber.deleteOne({date: date})
Copy the code

change

const data = await DateNumber.updateOne({date}, {$set: {list}})
Copy the code

example

const DateNumber = require('.. /models/dateNumber')

class DateNumberController {
    prefix = ' '
    getPath(name){
        return` /${this.prefix}/${name}`
    }
    async add(ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
            list: { type: "array", required: true },
        })
        const {date, list} = ctx.request.body
        const [err, data] = await to( new DateNumber({date, list}).save() )
        if(err) return ctx.throw(500, err)
        ctx.response.body = data
    }
    async find(ctx, next){
        const data = await DateNumber.find()
        ctx.response.body = data.join('\n')
        log.info('find')
    }
    async delect (ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
        })
        const {date} = ctx.request.body
        const data = await DateNumber.deleteOne({date: date})
        ctx.response.body = data
    }
    async update(ctx, next){
        ctx.verifyParams({
            date: { type: "string", required: true },
            list: { type: "array", required: true },
        })
        const {date, list} = ctx.request.body
        const [err, data] = await to( DateNumber.updateOne({date}, {$set: {list}}) )
        if(err) return ctx.throw(500, err)
        ctx.response.body = data
    }
}

module.exports = new DateNumberController()
Copy the code

Correspondence (from rookie Tutorial)

SQL terms/concepts MongoDB terminology/concepts Explanation/explanation
database database The database
table collection Database tables/collections
row document Data record line/document
column field Data fields/fields
index index The index
table joins Table joins,MongoDB does not support
primary key Primary key Specifies the primary key. MongoDB automatically sets the _ID field to the primary key

MAC needs to run Mongod first, and then open a window, otherwise it will remind you that the service can’t be found; Windows has built-in visualization software. Install mongoDB Compass

to function

The code above uses to

To is a wrapper around a promise, in the form of [err, data], which has the advantage of not having to write a try catch and handling errors horizontally.

To is global and is introduced in main.js

The advanced

Paging query

New datenumber.find ().skip(count *(page -1)).limit(count)Copy the code

It would be slow without an index

Join the left collection query

db.orders.aggregate([
   {
     $lookup:
       {
         from: "inventory".localField: "item",
         foreignField: "sku",
         as: "inventory_docs"}}])Copy the code

Join tables for more queries

The log

Use log4JS to implement logging

use

var log4js = require('log4js');
var logger = log4js.getLogger();
logger.level = 'debug';
logger.debug("Some debug messages");
Copy the code

Level

Logs of the current level are generated

Output Settings

I set that the info output is normal, and the output is divided by date (so that the file is not too big). If there is a big problem like error, the email will be sent. Example is as follows, including the test code, you can configure the account password in the email to run

// example email: {host:'smtp.qq.com',
        auth: {
            user: 'Your QQ id @qq.com',
            pass: 'Your password,',
        },
        recipients: 'Sender @126.com'
    }
}

const LOGINFO = {
    appenders: {
        info: {
            type: "DateFile",
            category: 'dateFileLog',
            filename: path.join(__dirname, './log/info/'),
            pattern: "yyyy-MM-dd.log",
            alwaysIncludePattern: true
        },
        email: {
            type: '@log4js-node/smtp', // Sender: config.email.auth.user, // subject:'Latest error report',
            SMTP: {
                host: config.email.host, 
                auth: config.email.auth,
            },
            recipients: config.email.recipients
        }
    },
}
const log4js = require('log4js')
log4js.configure(LOGINFO)

const log_info = log4js.getLogger()
const log_error = log4js.getLogger('error') global.log = { debug: log_info.debug.bind(log_info), info: log_info.info.bind(log_info), warn: log_info.warn.bind(log_info), error: log_error.error.bind(log_error), fatal: Log_error.fatal. Bind (log_error),setTimeout(() => {
    log.fatal({
        msg: 'test',
        err: 'fatal'})}, 400).Copy the code

Mailbox key access: enter qq mailbox, set up — — — — — — — — — — — > > account opening service: POP3 / SMTP service — — — — – > generate the authorization code

log.fatal({
        msg: 'test',
        err: 'fatal'
})
Copy the code

The effect

For details about log4js, see log4js github. For details about log4js email, see log4js-node/ SMTP github

other

Please give me a thumbs up. I’m going to level 3. Thank you

— 完 —