perf: 优化
This commit is contained in:
parent
51dafe0f9a
commit
eede990ec8
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package",
|
"$schema": "https://json.schemastore.org/package",
|
||||||
"name": "@kevisual/router",
|
"name": "@kevisual/router",
|
||||||
"version": "0.0.18",
|
"version": "0.0.20",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/router.js",
|
"main": "./dist/router.js",
|
||||||
@ -21,18 +21,19 @@
|
|||||||
"author": "abearxiong",
|
"author": "abearxiong",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@kevisual/query": "^0.0.18",
|
||||||
"@rollup/plugin-alias": "^5.1.1",
|
"@rollup/plugin-alias": "^5.1.1",
|
||||||
"@rollup/plugin-commonjs": "^28.0.3",
|
"@rollup/plugin-commonjs": "^28.0.3",
|
||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||||
"@rollup/plugin-typescript": "^12.1.2",
|
"@rollup/plugin-typescript": "^12.1.2",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.15.18",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"@types/xml2js": "^0.4.14",
|
"@types/xml2js": "^0.4.14",
|
||||||
"cookie": "^1.0.2",
|
"cookie": "^1.0.2",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"rollup": "^4.40.0",
|
"rollup": "^4.40.2",
|
||||||
"rollup-plugin-dts": "^6.2.1",
|
"rollup-plugin-dts": "^6.2.1",
|
||||||
"ts-loader": "^9.5.2",
|
"ts-loader": "^9.5.2",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
@ -40,7 +41,7 @@
|
|||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"ws": "npm:@kevisual/ws",
|
"ws": "npm:@kevisual/ws",
|
||||||
"xml2js": "^0.6.2",
|
"xml2js": "^0.6.2",
|
||||||
"zod": "^3.24.3"
|
"zod": "^3.24.4"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { QueryRouterServer, RouteOpts, Run, RouteMiddleware } from '@kevisual/router';
|
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[]> = {
|
// export type RouteObject<T extends readonly string[]> = {
|
||||||
// [K in T[number]]: RouteOpts;
|
// [K in T[number]]: RouteOpts;
|
||||||
// };
|
// };
|
||||||
@ -70,17 +70,46 @@ class Chain {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
type QueryChainOptions = {
|
||||||
|
query?: Query;
|
||||||
|
omitKeys?: string[];
|
||||||
|
};
|
||||||
class QueryChain {
|
class QueryChain {
|
||||||
obj: SimpleObject = {};
|
obj: SimpleObject = {};
|
||||||
constructor(value?: SimpleObject, opts?: SimpleObject) {
|
query: Query;
|
||||||
|
omitKeys: string[] = ['metadata', 'description', 'validator'];
|
||||||
|
constructor(value?: SimpleObject, opts?: QueryChainOptions) {
|
||||||
this.obj = value || {};
|
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 {
|
return {
|
||||||
...this.obj,
|
...obj,
|
||||||
...queryData,
|
...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 = {
|
export const util = {
|
||||||
getChain: (obj: RouteOpts, opts?: ChainOptions) => {
|
getChain: (obj: RouteOpts, opts?: ChainOptions) => {
|
||||||
@ -91,9 +120,11 @@ export const util = {
|
|||||||
export class QueryUtil<T extends RouteObject = RouteObject> {
|
export class QueryUtil<T extends RouteObject = RouteObject> {
|
||||||
obj: T;
|
obj: T;
|
||||||
app: QueryRouterServer;
|
app: QueryRouterServer;
|
||||||
constructor(object: T, opts?: ChainOptions) {
|
query: Query;
|
||||||
|
constructor(object: T, opts?: ChainOptions & QueryChainOptions) {
|
||||||
this.obj = object;
|
this.obj = object;
|
||||||
this.app = opts?.app;
|
this.app = opts?.app;
|
||||||
|
this.query = opts?.query;
|
||||||
}
|
}
|
||||||
static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions) {
|
static createFormObj<U extends RouteObject>(object: U, opts?: ChainOptions) {
|
||||||
return new QueryUtil<U>(object, opts);
|
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) {
|
chain<K extends keyof T>(key: K, opts?: ChainOptions) {
|
||||||
const obj = this.obj[key];
|
const obj = this.obj[key];
|
||||||
let newOpts = { app: this.app, ...opts };
|
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];
|
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() {
|
get routeObject() {
|
||||||
return this.obj;
|
return this.obj;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { pathToRegexp, Key } from 'path-to-regexp';
|
import { pathToRegexp, Key } from 'path-to-regexp';
|
||||||
import type { IncomingMessage, ServerResponse } from 'node:http';
|
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> };
|
type Req = IncomingMessage & { params?: Record<string, string> };
|
||||||
interface Route {
|
interface Route {
|
||||||
@ -24,6 +24,7 @@ export class SimpleRouter {
|
|||||||
getSearch(req: Req) {
|
getSearch(req: Req) {
|
||||||
return parseSearch(req);
|
return parseSearch(req);
|
||||||
}
|
}
|
||||||
|
parseSearchValue = parseSearchValue;
|
||||||
use(method: string, route: string, ...fns: Array<(req: Req, res: ServerResponse) => Promise<void> | void>) {
|
use(method: string, route: string, ...fns: Array<(req: Req, res: ServerResponse) => Promise<void> | void>) {
|
||||||
const handlers = Array.isArray(fns) ? fns.flat() : [];
|
const handlers = Array.isArray(fns) ? fns.flat() : [];
|
||||||
const pattern = pathToRegexp(route);
|
const pattern = pathToRegexp(route);
|
||||||
|
@ -10,7 +10,39 @@ export const parseBody = async <T = Record<string, any>>(req: IncomingMessage) =
|
|||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
try {
|
try {
|
||||||
const body = Buffer.concat(arr).toString();
|
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) {
|
} catch (e) {
|
||||||
resolve({} as T);
|
resolve({} as T);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user