perf: 优化

This commit is contained in:
熊潇 2025-05-15 22:32:05 +08:00
parent 51dafe0f9a
commit eede990ec8
4 changed files with 82 additions and 14 deletions

View File

@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package",
"name": "@kevisual/router",
"version": "0.0.18",
"version": "0.0.20",
"description": "",
"type": "module",
"main": "./dist/router.js",
@ -21,18 +21,19 @@
"author": "abearxiong",
"license": "MIT",
"devDependencies": {
"@kevisual/query": "^0.0.18",
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-typescript": "^12.1.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.14.1",
"@types/node": "^22.15.18",
"@types/ws": "^8.18.1",
"@types/xml2js": "^0.4.14",
"cookie": "^1.0.2",
"lodash-es": "^4.17.21",
"nanoid": "^5.1.5",
"rollup": "^4.40.0",
"rollup": "^4.40.2",
"rollup-plugin-dts": "^6.2.1",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
@ -40,7 +41,7 @@
"typescript": "^5.8.3",
"ws": "npm:@kevisual/ws",
"xml2js": "^0.6.2",
"zod": "^3.24.3"
"zod": "^3.24.4"
},
"repository": {
"type": "git",

View File

@ -1,5 +1,5 @@
import type { QueryRouterServer, RouteOpts, Run, RouteMiddleware } from '@kevisual/router';
import type { DataOpts, Query, Result } from '@kevisual/query/query';
// export type RouteObject<T extends readonly string[]> = {
// [K in T[number]]: RouteOpts;
// };
@ -70,17 +70,46 @@ class Chain {
return this;
}
}
type QueryChainOptions = {
query?: Query;
omitKeys?: string[];
};
class QueryChain {
obj: SimpleObject = {};
constructor(value?: SimpleObject, opts?: SimpleObject) {
query: Query;
omitKeys: string[] = ['metadata', 'description', 'validator'];
constructor(value?: SimpleObject, opts?: QueryChainOptions) {
this.obj = value || {};
this.query = opts?.query;
if (opts?.omitKeys) this.omitKeys = opts.omitKeys;
}
get(queryData?: Record<string, any>): Pick<RouteOpts, 'path' | 'key' | 'metadata' | 'description' | 'validator'> {
omit(obj: SimpleObject, key: string[] = []) {
const newObj = { ...obj };
key.forEach((k) => {
delete newObj[k];
});
return newObj;
}
/**
*
* @param queryData
* @returns
*/
getKey(queryData?: SimpleObject): Pick<RouteOpts, 'path' | 'key' | 'metadata' | 'description' | 'validator'> {
const obj = this.omit(this.obj, this.omitKeys);
return {
...this.obj,
...obj,
...queryData,
};
}
post<R = SimpleObject, P = SimpleObject>(data: P, options?: DataOpts): Promise<Result<R>> {
const _queryData = this.getKey(data);
return this.query.post(_queryData, options);
}
get<R = SimpleObject, P = SimpleObject>(data: P, options?: DataOpts): Promise<Result<R>> {
const _queryData = this.getKey(data);
return this.query.get(_queryData, options);
}
}
export const util = {
getChain: (obj: RouteOpts, opts?: ChainOptions) => {
@ -91,9 +120,11 @@ export const util = {
export class QueryUtil<T extends RouteObject = RouteObject> {
obj: T;
app: QueryRouterServer;
constructor(object: T, opts?: ChainOptions) {
query: Query;
constructor(object: T, opts?: ChainOptions & QueryChainOptions) {
this.obj = object;
this.app = opts?.app;
this.query = opts?.query;
}
static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions) {
return new QueryUtil<U>(object, opts);
@ -108,12 +139,15 @@ export class QueryUtil<T extends RouteObject = RouteObject> {
chain<K extends keyof T>(key: K, opts?: ChainOptions) {
const obj = this.obj[key];
let newOpts = { app: this.app, ...opts };
return new Chain(obj, newOpts);
return new QueryUtil.Chain(obj, newOpts);
}
queryChain<K extends keyof T>(key: K) {
queryChain<K extends keyof T>(key: K, opts?: QueryChainOptions) {
const value = this.obj[key];
return new QueryChain(value);
let newOpts = { query: this.query, ...opts };
return new QueryUtil.QueryChain(value, newOpts);
}
static Chain = Chain;
static QueryChain = QueryChain;
get routeObject() {
return this.obj;
}

View File

@ -1,6 +1,6 @@
import { pathToRegexp, Key } from 'path-to-regexp';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { parseBody, parseSearch } from './server/parse-body.ts';
import { parseBody, parseSearch, parseSearchValue } from './server/parse-body.ts';
type Req = IncomingMessage & { params?: Record<string, string> };
interface Route {
@ -24,6 +24,7 @@ export class SimpleRouter {
getSearch(req: Req) {
return parseSearch(req);
}
parseSearchValue = parseSearchValue;
use(method: string, route: string, ...fns: Array<(req: Req, res: ServerResponse) => Promise<void> | void>) {
const handlers = Array.isArray(fns) ? fns.flat() : [];
const pattern = pathToRegexp(route);

View File

@ -10,7 +10,39 @@ export const parseBody = async <T = Record<string, any>>(req: IncomingMessage) =
req.on('end', () => {
try {
const body = Buffer.concat(arr).toString();
resolve(JSON.parse(body));
// 获取 Content-Type 头信息
const contentType = req.headers['content-type'] || '';
// 处理 application/json
if (contentType.includes('application/json')) {
resolve(JSON.parse(body) as T);
return;
}
// 处理 application/x-www-form-urlencoded
if (contentType.includes('application/x-www-form-urlencoded')) {
const formData = new URLSearchParams(body);
const result: Record<string, any> = {};
formData.forEach((value, key) => {
// 尝试将值解析为 JSON如果失败则保留原始字符串
try {
result[key] = JSON.parse(value);
} catch {
result[key] = value;
}
});
resolve(result as T);
return;
}
// 默认尝试 JSON 解析
try {
resolve(JSON.parse(body) as T);
} catch {
resolve({} as T);
}
} catch (e) {
resolve({} as T);
}