route-intercept.js 2.4 KB
/**
 * 路由拦截
 * @author: yyq<yanqing.yang@yoho.cn>
 * @date: 2018/1/22
 */

const _ = require('lodash');
const express = require('express');
const methods = require('methods');

const intercept = (app) => {
    // 拦截调度器,获取原路径
    app.use = ((appUse) => {
        return (...args) => {
            let rootPath = '';
            const arg = args[0];

            if (typeof arg !== 'function') {
                rootPath = arg;
            }

            app.locals.rootPath = rootPath || '';

            return appUse.call(app, ...args);
        };
    })(app.use);


    // 拦截路由方法,解析新注册方式
    express.Router = ((_router) => {
        const baseRouter = _router();

        return () => {
            let router = _router();

            methods.concat('all').forEach((method) => {
                router[method] = (path, ...args) => {
                    const arg = args[0];

                    if (typeof arg !== 'function') {
                        args = _.drop(args);

                        router.rootRouter = router.rootRouter || [];

                        router.rootRouter.push({
                            path: arg,
                            relatedPath: path,
                            method: method,
                            args: args
                        });
                    }

                    return baseRouter[method].call(router, path, ...args);
                };
            });

            return router;
        };
    })(express.Router);
};


// 注册根路由
const regist = (app, parent, router) => {
    if (router.rootRouter && router.rootRouter.length) {
        let rootPath = '';

        if (app.locals.rootPath && _.isString(app.locals.rootPath)) {
            rootPath = app.locals.rootPath;
        }

        router.rootRouter.forEach(el => {
            let fullPath = rootPath;

            if (el.relatedPath && _.isString(el.relatedPath)) {
                fullPath += el.relatedPath;
            }

            const pathArr = _.compact(fullPath.split('/'));

            parent[el.method](el.path, (req, res, next) => {
                Object.assign(res.locals, {
                    module: pathArr[0] || res.locals.module,
                    page: pathArr[1] || res.locals.page
                });

                return next();
            }, ...el.args);
        });
    }
};

module.exports = {
    intercept,
    regist
};