UNPKG

ssocket

Version:

仿 Koa 中间件控制的 WebSocket 服务

197 lines (196 loc) 5.78 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Router = void 0; const path_to_regexp_1 = require("path-to-regexp"); const events_1 = require("events"); const logger_1 = __importDefault(require("./logger")); const logger = logger_1.default("router"); const emitter = new events_1.EventEmitter(); /**路由对象 */ class Layer { /** * 节点构造器 * @param path 节点名称 * @param middleware 中间件列表 * @param opts 配置 */ constructor(path, middleware, opts = {}) { this.opts = opts; this.path = path; this.paramNames = []; this.stack = Array.isArray(middleware) ? middleware : [middleware]; this.regexp = path_to_regexp_1.pathToRegexp(path, this.paramNames, this.opts); this.name = opts.name; } /** * 判断路径是否匹配此路由 * @param path */ match(path) { return this.regexp.test(path); } /** * 设置节点头部 * @param prefix */ setPrefix(prefix) { if (this.path) { this.path = prefix + this.path; this.paramNames = []; this.regexp = path_to_regexp_1.pathToRegexp(this.path, this.paramNames, this.opts); } return this; } } /** * 生成路由栈调用函数 * @param middleware */ function compose(middleware) { /** * @param {Object} context * @return {Promise} * @api public */ return function (context, next) { // last called middleware # let index = -1; function dispatch(i) { if (i <= index) return Promise.reject(new Error('next() called multiple times')); index = i; let fn = middleware[i]; // 最后一个 if (i === middleware.length) fn = next; if (!fn) return Promise.resolve(); try { return Promise.resolve(fn(context, function next() { return dispatch(i + 1); })); } catch (err) { return Promise.reject(err); } } return dispatch(0); }; } /** * 路由节点 */ class Router extends events_1.EventEmitter { constructor() { super(); /**路由栈 */ this.stack = []; this.opts = {}; logger("constructor"); } get emitter() { return emitter; } /** * 创建并注册一条路线 * @param path * @param middleware * @param opts */ register(path, middleware, opts = {}) { // create route var route = new Layer(path, middleware, { end: opts.end === false ? opts.end : true, name: opts.name, sensitive: false, strict: false, prefix: "", ignoreCaptures: opts.ignoreCaptures }); logger("register", { path, middleware, opts, route }); this.stack.push(route); return route; } /** * 从路径获取到匹配的路由节点 * @param path */ match(path) { var layer; var matchedLayers = []; for (var len = this.stack.length, i = 0; i < len; i++) { layer = this.stack[i]; if (layer.match(path)) { matchedLayers.push(layer); } } logger("match", { path, matchedLayers }); return matchedLayers; } /** * 绑定节点函数 * @param path * @param middleware */ ONPath(path, ...middleware) { logger("ONPath", { path, middleware }); this.register(path, middleware, { name: path }); return this; } /** * 绑定节点树 * @param middleware */ USEPathMiddleware(path, ...middleware) { var router = this; middleware.forEach(function (m) { if (m.prototype.router) { m.prototype.router.stack.forEach(function (nestedLayer) { nestedLayer.setPrefix(path); if (router.opts.prefix) nestedLayer.setPrefix(router.opts.prefix); router.stack.push(nestedLayer); }); } else { router.register(path, m, { end: false, ignoreCaptures: false }); } }); logger("USEPathMiddleware", { path, middleware }); return this; } USEMiddleware(...middleware) { var router = this; middleware.forEach(function (m) { if (m.prototype && m.prototype.router) { m.prototype.router.stack.forEach(function (nestedLayer) { if (router.opts.prefix) nestedLayer.setPrefix(router.opts.prefix); router.stack.push(nestedLayer); }); } else { router.register('(.*)', m, { end: false, ignoreCaptures: true }); } }); logger("USEPathMiddleware", { middleware }); return this; } /** * 获取路由调用方法 */ get routes() { var router = this; var dispatch = function dispatch(ctx, next) { var layerChain = router.match(ctx.path).reduce(function (memo, layer) { return memo.concat(layer.stack); }, []); return compose(layerChain)(ctx, next); }; dispatch.prototype.router = this; logger("routes", { dispatch }); return dispatch; } } exports.Router = Router;