From 1c3e65df8ac2b8da5201e4cde444e32b6a51e43b Mon Sep 17 00:00:00 2001 From: xion Date: Wed, 26 Feb 2025 11:26:52 +0800 Subject: [PATCH] feat: add metadata and middleware add preivew middleware --- demo/simple/src/apps-https/app.ts | 2 +- demo/simple/src/three-link/three.ts | 52 ++++++++++++++++++++++ package.json | 2 +- src/route.ts | 67 ++++++++++++++++++++--------- 4 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 demo/simple/src/three-link/three.ts diff --git a/demo/simple/src/apps-https/app.ts b/demo/simple/src/apps-https/app.ts index 68d0bdb..ba75fa2 100644 --- a/demo/simple/src/apps-https/app.ts +++ b/demo/simple/src/apps-https/app.ts @@ -3,7 +3,7 @@ import { readFileSync } from 'fs'; const app = new App({ serverOptions: { cors: {}, - isHTTPS: true, + httpType: 'https', httpsKey: readFileSync('https-key.pem', 'utf8'), httpsCert: readFileSync('https-cert.pem', 'utf-8'), }, diff --git a/demo/simple/src/three-link/three.ts b/demo/simple/src/three-link/three.ts new file mode 100644 index 0000000..d6ff172 --- /dev/null +++ b/demo/simple/src/three-link/three.ts @@ -0,0 +1,52 @@ +import { Route, App } from '@kevisual/router'; +import { readFileSync } from 'fs'; +const app = new App({ + serverOptions: { + cors: {}, + httpType: 'https', + httpsKey: readFileSync('https-key.pem', 'utf8'), + httpsCert: readFileSync('https-cert.pem', 'utf-8'), + }, +}); + +app + .route({ + path: 'demo', + key: '01', + }) + .define(async (ctx) => { + ctx.token = '01'; + ctx.body = '01'; + ctx.state.t01 = '01'; + console.log('state01', ctx.state); + }) + .addTo(app); + +app + .route({ + path: 'demo', + key: '02', + middleware: [{ path: 'demo', key: '01' } as Route], + }) + .define(async (ctx) => { + ctx.body = '02'; + ctx.state.t02 = '02'; + console.log('state02', ctx.state, 't', ctx.token); + }) + .addTo(app); + +app + .route({ + path: 'demo', + key: '03', + middleware: [{ path: 'demo', key: '02' } as Route], + }) + .define(async (ctx) => { + ctx.body = '03'; + console.log('state03', ctx.state); + }) + .addTo(app); + +app.call({ path: 'demo', key: '03' }).then((ctx) => { + console.log('result', ctx.body); +}); diff --git a/package.json b/package.json index c1aa836..40b6024 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package", "name": "@kevisual/router", - "version": "0.0.6", + "version": "0.0.7", "description": "", "main": "dist/index.js", "module": "dist/index.js", diff --git a/src/route.ts b/src/route.ts index 4fcc3a5..00d0fa5 100644 --- a/src/route.ts +++ b/src/route.ts @@ -48,6 +48,7 @@ export type RouteOpts = { run?: Run; nextRoute?: NextRoute; // route to run after this route description?: string; + metadata?: { [key: string]: any }; middleware?: Route[] | string[]; // middleware type?: 'route' | 'middleware'; /** @@ -73,19 +74,32 @@ export type DefineRouteOpts = Omit; export class Route { + /** + * 一级路径 + */ path?: string; + /** + * 二级路径 + */ key?: string; id?: string; share? = false; run?: Run; nextRoute?: NextRoute; // route to run after this route description?: string; + metadata?: { [key: string]: any }; middleware?: (Route | string)[]; // middleware type? = 'route'; private _validator?: { [key: string]: Rule }; schema?: { [key: string]: Schema }; data?: any; + /** + * 是否需要验证 + */ isVerify?: boolean; + /** + * 是否开启debug,开启后会打印错误信息 + */ isDebug?: boolean; constructor(path: string, key: string = '', opts?: RouteOpts) { path = path.trim(); @@ -100,6 +114,7 @@ export class Route { this.run = opts.run; this.nextRoute = opts.nextRoute; this.description = opts.description; + this.metadata = opts.metadata; this.type = opts.type || 'route'; this.validator = opts.validator; this.middleware = opts.middleware || []; @@ -218,7 +233,7 @@ export class Route { // 全覆盖,所以opts需要准确,不能由idUsePath 需要check的变量 const setOpts = (opts: DefineRouteOpts) => { const keys = Object.keys(opts); - const checkList = ['path', 'key', 'run', 'nextRoute', 'description', 'middleware', 'type', 'validator', 'isVerify', 'isDebug']; + const checkList = ['path', 'key', 'run', 'nextRoute', 'description', 'metadata', 'middleware', 'type', 'validator', 'isVerify', 'isDebug']; for (let item of keys) { if (!checkList.includes(item)) { continue; @@ -319,28 +334,38 @@ export class QueryRouter { // run middleware if (route && route.middleware && route.middleware.length > 0) { const errorMiddleware: { path?: string; key?: string; id?: string }[] = []; - // TODO: 向上递归执行动作, 暂时不考虑 - const routeMiddleware = route.middleware.map((m) => { - let route: Route | undefined; - const isString = typeof m === 'string'; - if (typeof m === 'string') { - route = this.routes.find((r) => r.id === m); - } else { - route = this.routes.find((r) => r.path === m.path && r.key === m.key); - } - if (!route) { + const getMiddleware = (m: Route) => { + if (!m.middleware || m.middleware.length === 0) return []; + const routeMiddleware: Route[] = []; + for (let i = 0; i < m.middleware.length; i++) { + const item = m.middleware[i]; + let route: Route | undefined; + const isString = typeof item === 'string'; if (isString) { - errorMiddleware.push({ - id: m as string, - }); - } else - errorMiddleware.push({ - path: m?.path, - key: m?.key, - }); + route = this.routes.find((r) => r.id === item); + } else { + route = this.routes.find((r) => r.path === item.path && r.key === item.key); + } + if (!route) { + if (isString) { + errorMiddleware.push({ + id: item as string, + }); + } else + errorMiddleware.push({ + path: m?.path, + key: m?.key, + }); + } + const routeMiddlewarePrevious = getMiddleware(route); + if (routeMiddlewarePrevious.length > 0) { + routeMiddleware.push(...routeMiddlewarePrevious); + } + routeMiddleware.push(route); } - return route; - }); + return routeMiddleware; + }; + const routeMiddleware = getMiddleware(route); if (errorMiddleware.length > 0) { console.error('middleware not found'); ctx.body = errorMiddleware;