This is the second day of my participation in Gwen Challenge

Step1: Simple handwriting ultra simple version of KOA small frame (Pok) ✨

Simple functions implemented πŸ”‹

  • Setting up the HTTP Service
  • Simple route construction
  • Middleware composition
  • Request and Response encapsulation

Key points

  • Context context. Js

File directory content πŸ“Œ

  • app.js
  • pok.js
  • context.js
  • response.js
  • router.js

Test file (app.js) πŸ“œ

const Pok = require('./pok')
const app = new Pok()
// ==============Router start================
const Router = require('./router')
const router = new Router()

router.get('/index'.async ctx => { ctx.body = 'index page'; });
router.get('/post'.async ctx => { ctx.body = 'post page'; });
router.get('/list'.async ctx => { ctx.body = 'list page'; });
router.post('/index'.async ctx => { ctx.body = 'post page'; });
app.use(router.routes());
// ==============Router end================
app.listen(3001.() = >{
    console.log('Service started');
})
Copy the code

Encapsulate a koA-like framework, pokπŸ“œ

// Introduce the base library
const http = require('http')
const context = require('./context')
const request = require('./request')
const response = require('./response')
//Pok
class Pok{
    constructor(){
        this.middlewares = []
    }
    listen(. args){
        const server = http.createServer(async (req,res)=>{
            // Create content context
            const ctx = this.createContext(req,res);
            // Merge middleware
            const fn = this.compose(this.middlewares)
            awaitfn(ctx) res.end(ctx.body) }) server.listen(... args) }use(middleware){
        this.middlewares.push(middleware)
    }
    // Create content context
    createContext(req,res){
        const ctx = Object.create(context)
        ctx.request = Object.create(request)
        ctx.response = Object.create(response)
        ctx.request.req = req
        ctx.response.res = res
        return ctx
    }
    / / middleware
    compose(middlewares){
        return function(ctx){
            return ds(0)
            function ds(i){
                let fn = middlewares[i]
                if(! fn){return Promise.resolve()
                }else{
                    return Promise.resolve(
                        fn(ctx,function next(){
                            return ds(i+1)})}}}}}module.exports = Pok
Copy the code

Route encapsulation (router.js) πŸ“œ

class Router {
    constructor() {
        this.stack = []
    }
    resigter(method, path, middleware) {
        this.stack.push({method, path, middleware})
    }
    get(path, middleware) {
        this.resigter('get', path, middleware)
    }
    post(path, middleware) {
        this.resigter('post', path, middleware)
    }
    routes() {
        let stock = this.stack;
        return async function(ctx, next) {
          let currentPath = ctx.url;
          console.log(currentPath);
          let route;
    
          for (let i = 0; i < stock.length; i++) {
            let item = stock[i];
            console.log(item);
            if (currentPath === item.path && item.method.indexOf(ctx.method) >= 0) {
              // Determine path and method
              route = item.middleware;
              break; }}if (typeof route === 'function') {
            route(ctx, next);
            return;
          }
    
          awaitnext(); }; }}module.exports = Router
Copy the code

Request and Response encapsulation (request.js)πŸ“œ

module.exports = {
    get url() {return this.req.url
    },
    get method() {return this.req.method.toLowerCase()
    }
};
response.js
module.exports = {
    get body() {return this._body
    },
    set body(val) {this._body = val
    }
};
Copy the code

Context encapsulation (context.js) πŸ“œ

module.exports = {
    get url() {
        return this.request.url
    },
    get body() {
        return this.response.body
    },
    set body(val) {this.response.body = val
    },
    get method() {
        return this.request.method
    }
}
Copy the code

Step2: simply write Egg framework to implement MVC layering (based on koa)

Simple functions implemented πŸ”‹

  • Encapsulate KOA and implement MVC layering

Main contents πŸ“Œ

  • initRouter
  • initController
  • initService
  • LoadConfig
  • Updated…

Test file (app.js) πŸ“œ

const pgg = require('./pgg')
const app = new pgg()
app.start(3000) # Encapsulate an Egg-like framework PGGconst koa = require('koa');
const {initRouter, initController, initService,LoadConfig} = require('./pgg-loader')
class Pgg{
    constructor(conf){
        this.$app = new koa(conf)
        LoadConfig(this)
        this.$service = initService(this)
        this.$ctrl = initController(this)
        this.$router = initRouter(this)
        // Mount the route
        console.dir(this.$ctrl);
        // Call the routes function
        this.$app.use(this.$router.routes())
    }
    start(port){
        this.$app.listen(port,() = >{
            console.log(` server${port}Successful startup '); }}})module.exports = Pgg
Copy the code

Read different files (pgg-loader.js) πŸ“œ

const fs = require('fs')
const path = require('path')
const Router = require('koa-router')
const Sequelize =  require('sequelize')
// Read files to convert method paths and functions into objects
function load(dir,cb) {
    // Convert to absolute path
    const url = path.resolve(__dirname,dir)
    // Read the names of all files in the specified directory.
    const files = fs.readdirSync(url)
    // Walk through the file and read the contents
    files.forEach(filename= >{
        filename = filename.replace('.js'.' ')
        const file= require(url+'/'+filename)
        console.log(filename,'File name');
        // File name
        cb(filename,file)
    })
}
// Initialize the routing page
function initRouter(app) {
    const router = new Router()
    // Initializes the routing file in the route file path
    load("routes".(filename,routes) = >{
        // index prefix processing
        const prefix = filename === 'index'?' ':` /${filename}`
        // Determine the route type
        routes = typeof routes=== 'function'? routes(app):routes// Iterate over the add route configuration
        Object.keys(routes) .forEach(key= >{
            // Get the request method and path
            const[method,path] = key.split(' ');
            console.log(` ${method.toLocaleUpperCase()} ${prefix}${path}\n,${routes[key]}`);
            router[method](prefix + path,async ctx=>{
                app.ctx = ctx
                await routes[key](ctx)
            })
        })
    })
    return router
}
// Control layer initialization
function initController(app) {
    const controllers = {}
    load('controller'.(filename,controller) = >{
        controllers[filename] = controller(app)
    })
    return controllers
}
// Initialization of the service layer
function initService() {
    const services = {}
    load('service'.(filename,service) = >{
        services[filename] = service
    })
    return services
}
// Configure persistence
function LoadConfig(app) { 
    load('config'.(filename,config) = >{
        if(config.db){
            app.$db = new Sequelize(config.db)
        }
        app.$model = {}
        load('model'.(filename,{schema, options}) = >{ app.$model[filename] = app.$db.define(filename, schema, options) }); app.$db.sync(); })}// Initialization of the persistence layer
module.exports = {initRouter,initController,initService,LoadConfig}
Copy the code

I’ll put the file ingithubon

Welcome to follow the author, thanks for your support β—β˜˜