feat: add metadata and middleware add preivew middleware

This commit is contained in:
xion 2025-02-26 11:26:52 +08:00
parent 986b5687c4
commit 1c3e65df8a
4 changed files with 100 additions and 23 deletions

View File

@ -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'),
},

View File

@ -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);
});

View File

@ -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",

View File

@ -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<RouteOpts, 'idUsePath' | 'verify' | 'verifyKe
const pickValue = ['path', 'key', 'id', 'description', 'type', 'validator', 'middleware'] as const;
export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
export class Route<U = { [key: string]: any }> {
/**
*
*/
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<any> };
data?: any;
/**
*
*/
isVerify?: boolean;
/**
* debug
*/
isDebug?: boolean;
constructor(path: string, key: string = '', opts?: RouteOpts) {
path = path.trim();
@ -100,6 +114,7 @@ export class Route<U = { [key: string]: any }> {
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<U = { [key: string]: any }> {
// 全覆盖所以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;