vafast 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/token.d.ts +40 -0
- package/dist/auth/token.js +124 -0
- package/dist/defineRoute.d.ts +2 -0
- package/dist/defineRoute.js +3 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +14 -0
- package/dist/middleware/auth.js +106 -0
- package/dist/middleware/authMiddleware.d.ts +2 -0
- package/dist/middleware/authMiddleware.js +13 -0
- package/dist/middleware/component-renderer.d.ts +6 -0
- package/dist/middleware/component-renderer.js +136 -0
- package/dist/middleware/component-router.d.ts +10 -0
- package/dist/middleware/component-router.js +39 -0
- package/dist/middleware/cors.d.ts +9 -0
- package/dist/middleware/cors.js +30 -0
- package/dist/middleware/rateLimit.d.ts +8 -0
- package/dist/middleware/rateLimit.js +33 -0
- package/dist/middleware.d.ts +18 -0
- package/dist/middleware.js +51 -0
- package/dist/monitoring/index.d.ts +29 -0
- package/dist/monitoring/index.js +24 -0
- package/dist/monitoring/native-monitor.d.ts +38 -0
- package/dist/monitoring/native-monitor.js +176 -0
- package/dist/monitoring/types.d.ts +146 -0
- package/dist/monitoring/types.js +8 -0
- package/dist/router.d.ts +17 -0
- package/dist/router.js +74 -0
- package/dist/server/base-server.d.ts +38 -0
- package/dist/server/base-server.js +167 -0
- package/dist/server/component-server.d.ts +32 -0
- package/dist/server/component-server.js +146 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +9 -0
- package/dist/server/server-factory.d.ts +42 -0
- package/dist/server/server-factory.js +70 -0
- package/dist/server/server.d.ts +7 -0
- package/dist/server/server.js +73 -0
- package/dist/types/component-route.d.ts +25 -0
- package/dist/types/component-route.js +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/route.d.ts +39 -0
- package/dist/types/route.js +11 -0
- package/dist/types/types.d.ts +18 -0
- package/dist/types/types.js +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +1 -0
- package/dist/utils/base64url.d.ts +2 -0
- package/dist/utils/base64url.js +11 -0
- package/dist/utils/dependency-manager.d.ts +23 -0
- package/dist/utils/dependency-manager.js +67 -0
- package/dist/utils/go-await.d.ts +26 -0
- package/dist/utils/go-await.js +33 -0
- package/dist/utils/handle.d.ts +10 -0
- package/dist/utils/handle.js +24 -0
- package/dist/utils/html-renderer.d.ts +18 -0
- package/dist/utils/html-renderer.js +64 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/parsers.d.ts +36 -0
- package/dist/utils/parsers.js +126 -0
- package/dist/utils/path-matcher.d.ts +23 -0
- package/dist/utils/path-matcher.js +82 -0
- package/dist/utils/request-validator.d.ts +63 -0
- package/dist/utils/request-validator.js +94 -0
- package/dist/utils/response.d.ts +12 -0
- package/dist/utils/response.js +69 -0
- package/dist/utils/route-handler-factory.d.ts +50 -0
- package/dist/utils/route-handler-factory.js +182 -0
- package/dist/utils/validators/schema-validator.d.ts +66 -0
- package/dist/utils/validators/schema-validator.js +222 -0
- package/dist/utils/validators/schema-validators-ultra.d.ts +51 -0
- package/dist/utils/validators/schema-validators-ultra.js +289 -0
- package/dist/utils/validators/validators.d.ts +30 -0
- package/dist/utils/validators/validators.js +54 -0
- package/package.json +3 -4
- package/dist/index.cjs +0 -51
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -460
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 性能监控系统类型定义
|
|
3
|
+
*
|
|
4
|
+
* @author Framework Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
* @license MIT
|
|
7
|
+
*/
|
|
8
|
+
export interface BaseMetrics {
|
|
9
|
+
timestamp: number;
|
|
10
|
+
requestId: string;
|
|
11
|
+
method: string;
|
|
12
|
+
path: string;
|
|
13
|
+
statusCode: number;
|
|
14
|
+
userAgent?: string;
|
|
15
|
+
ip?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface PerformanceMetrics extends BaseMetrics {
|
|
18
|
+
totalTime: number;
|
|
19
|
+
routeMatchTime: number;
|
|
20
|
+
validationTime: number;
|
|
21
|
+
handlerTime: number;
|
|
22
|
+
responseTime: number;
|
|
23
|
+
memoryUsage: {
|
|
24
|
+
heapUsed: number;
|
|
25
|
+
heapTotal: number;
|
|
26
|
+
external: number;
|
|
27
|
+
rss: number;
|
|
28
|
+
};
|
|
29
|
+
validation: {
|
|
30
|
+
bodyValidated: boolean;
|
|
31
|
+
queryValidated: boolean;
|
|
32
|
+
paramsValidated: boolean;
|
|
33
|
+
headersValidated: boolean;
|
|
34
|
+
cookiesValidated: boolean;
|
|
35
|
+
validationErrors: number;
|
|
36
|
+
};
|
|
37
|
+
routing: {
|
|
38
|
+
routeFound: boolean;
|
|
39
|
+
middlewareCount: number;
|
|
40
|
+
dynamicParams: number;
|
|
41
|
+
};
|
|
42
|
+
error?: {
|
|
43
|
+
type: string;
|
|
44
|
+
message: string;
|
|
45
|
+
stack?: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface AggregatedMetrics {
|
|
49
|
+
timeRange: {
|
|
50
|
+
start: number;
|
|
51
|
+
end: number;
|
|
52
|
+
};
|
|
53
|
+
requests: {
|
|
54
|
+
total: number;
|
|
55
|
+
successful: number;
|
|
56
|
+
failed: number;
|
|
57
|
+
byMethod: Record<string, number>;
|
|
58
|
+
byPath: Record<string, number>;
|
|
59
|
+
byStatusCode: Record<number, number>;
|
|
60
|
+
};
|
|
61
|
+
performance: {
|
|
62
|
+
avgTotalTime: number;
|
|
63
|
+
avgRouteMatchTime: number;
|
|
64
|
+
avgValidationTime: number;
|
|
65
|
+
avgHandlerTime: number;
|
|
66
|
+
avgResponseTime: number;
|
|
67
|
+
p50TotalTime: number;
|
|
68
|
+
p90TotalTime: number;
|
|
69
|
+
p95TotalTime: number;
|
|
70
|
+
p99TotalTime: number;
|
|
71
|
+
minTotalTime: number;
|
|
72
|
+
maxTotalTime: number;
|
|
73
|
+
};
|
|
74
|
+
memory: {
|
|
75
|
+
avgHeapUsed: number;
|
|
76
|
+
avgHeapTotal: number;
|
|
77
|
+
maxHeapUsed: number;
|
|
78
|
+
maxHeapTotal: number;
|
|
79
|
+
};
|
|
80
|
+
validation: {
|
|
81
|
+
totalValidations: number;
|
|
82
|
+
validationErrors: number;
|
|
83
|
+
validationSuccessRate: number;
|
|
84
|
+
};
|
|
85
|
+
routing: {
|
|
86
|
+
totalRoutes: number;
|
|
87
|
+
routesWithMiddleware: number;
|
|
88
|
+
dynamicRoutes: number;
|
|
89
|
+
routeHitCount: Record<string, number>;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export interface MonitoringConfig {
|
|
93
|
+
enabled: boolean;
|
|
94
|
+
retention: {
|
|
95
|
+
maxRecords: number;
|
|
96
|
+
maxAge: number;
|
|
97
|
+
cleanupInterval: number;
|
|
98
|
+
};
|
|
99
|
+
samplingRate: number;
|
|
100
|
+
recordErrors: boolean;
|
|
101
|
+
recordBodySize: boolean;
|
|
102
|
+
recordResponseSize: boolean;
|
|
103
|
+
thresholds: {
|
|
104
|
+
slowRequest: number;
|
|
105
|
+
highMemoryUsage: number;
|
|
106
|
+
errorRate: number;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export interface MonitoringEvent {
|
|
110
|
+
type: 'request_start' | 'request_end' | 'validation_start' | 'validation_end' | 'error';
|
|
111
|
+
timestamp: number;
|
|
112
|
+
requestId: string;
|
|
113
|
+
data: any;
|
|
114
|
+
}
|
|
115
|
+
export interface PerformanceReport {
|
|
116
|
+
id: string;
|
|
117
|
+
timestamp: number;
|
|
118
|
+
timeRange: {
|
|
119
|
+
start: number;
|
|
120
|
+
end: number;
|
|
121
|
+
};
|
|
122
|
+
summary: {
|
|
123
|
+
totalRequests: number;
|
|
124
|
+
avgResponseTime: number;
|
|
125
|
+
errorRate: number;
|
|
126
|
+
memoryUsage: number;
|
|
127
|
+
};
|
|
128
|
+
details: {
|
|
129
|
+
topSlowestRoutes: Array<{
|
|
130
|
+
path: string;
|
|
131
|
+
avgTime: number;
|
|
132
|
+
count: number;
|
|
133
|
+
}>;
|
|
134
|
+
topErrorRoutes: Array<{
|
|
135
|
+
path: string;
|
|
136
|
+
errorCount: number;
|
|
137
|
+
errorRate: number;
|
|
138
|
+
}>;
|
|
139
|
+
memoryTrend: Array<{
|
|
140
|
+
timestamp: number;
|
|
141
|
+
heapUsed: number;
|
|
142
|
+
}>;
|
|
143
|
+
responseTimeDistribution: Record<string, number>;
|
|
144
|
+
};
|
|
145
|
+
recommendations: string[];
|
|
146
|
+
}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Route, NestedRoute, FlattenedRoute } from "./types";
|
|
2
|
+
export interface MatchResult {
|
|
3
|
+
matched: boolean;
|
|
4
|
+
params: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* 扁平化嵌套路由,计算完整路径和中间件链
|
|
8
|
+
*/
|
|
9
|
+
export declare function flattenNestedRoutes(routes: (Route | NestedRoute)[]): FlattenedRoute[];
|
|
10
|
+
/**
|
|
11
|
+
* 标准化路径:去重斜杠、解码URL、处理结尾斜杠
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizePath(path: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* 匹配函数:支持动态路由和路径标准化
|
|
16
|
+
*/
|
|
17
|
+
export declare function matchPath(pattern: string, path: string): MatchResult;
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 扁平化嵌套路由,计算完整路径和中间件链
|
|
3
|
+
*/
|
|
4
|
+
export function flattenNestedRoutes(routes) {
|
|
5
|
+
const flattened = [];
|
|
6
|
+
function processRoute(route, parentPath = "", parentMiddleware = []) {
|
|
7
|
+
const currentPath = parentPath + route.path;
|
|
8
|
+
const currentMiddleware = [...parentMiddleware, ...(route.middleware || [])];
|
|
9
|
+
if ('method' in route && 'handler' in route) {
|
|
10
|
+
// 这是一个叶子路由(有处理函数)
|
|
11
|
+
flattened.push({
|
|
12
|
+
...route,
|
|
13
|
+
fullPath: currentPath,
|
|
14
|
+
middlewareChain: currentMiddleware
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
else if ('children' in route && route.children) {
|
|
18
|
+
// 这是一个分组路由,处理子路由
|
|
19
|
+
for (const child of route.children) {
|
|
20
|
+
processRoute(child, currentPath, currentMiddleware);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
for (const route of routes) {
|
|
25
|
+
processRoute(route);
|
|
26
|
+
}
|
|
27
|
+
return flattened;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 标准化路径:去重斜杠、解码URL、处理结尾斜杠
|
|
31
|
+
*/
|
|
32
|
+
export function normalizePath(path) {
|
|
33
|
+
// 解码 URL 编码的字符
|
|
34
|
+
let normalized = decodeURIComponent(path);
|
|
35
|
+
// 去重连续的斜杠
|
|
36
|
+
normalized = normalized.replace(/\/+/g, "/");
|
|
37
|
+
// 处理根路径
|
|
38
|
+
if (normalized === "")
|
|
39
|
+
normalized = "/";
|
|
40
|
+
// 去掉结尾斜杠(除非是根路径)
|
|
41
|
+
if (normalized !== "/" && normalized.endsWith("/")) {
|
|
42
|
+
normalized = normalized.slice(0, -1);
|
|
43
|
+
}
|
|
44
|
+
return normalized;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 匹配函数:支持动态路由和路径标准化
|
|
48
|
+
*/
|
|
49
|
+
export function matchPath(pattern, path) {
|
|
50
|
+
// 标准化输入路径
|
|
51
|
+
const normalizedPath = normalizePath(path);
|
|
52
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
53
|
+
const pathParts = normalizedPath.split("/").filter(Boolean);
|
|
54
|
+
const params = {};
|
|
55
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
56
|
+
const pat = patternParts[i];
|
|
57
|
+
const part = pathParts[i];
|
|
58
|
+
if (pat === "*") {
|
|
59
|
+
params["*"] = pathParts.slice(i).join("/");
|
|
60
|
+
return { matched: true, params };
|
|
61
|
+
}
|
|
62
|
+
if (pat.startsWith(":")) {
|
|
63
|
+
if (!part)
|
|
64
|
+
return { matched: false, params: {} };
|
|
65
|
+
params[pat.slice(1)] = part;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (pat !== part)
|
|
69
|
+
return { matched: false, params: {} };
|
|
70
|
+
}
|
|
71
|
+
if (patternParts.length !== pathParts.length)
|
|
72
|
+
return { matched: false, params: {} };
|
|
73
|
+
return { matched: true, params };
|
|
74
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Middleware } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* 服务器基类
|
|
4
|
+
* 包含所有服务器类型的公共逻辑
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class BaseServer {
|
|
7
|
+
protected globalMiddleware: Middleware[];
|
|
8
|
+
use(mw: Middleware): void;
|
|
9
|
+
/**
|
|
10
|
+
* 打印扁平化后的路由信息,用于调试
|
|
11
|
+
*/
|
|
12
|
+
protected logFlattenedRoutes(routes: any[], type?: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* 检测路由冲突
|
|
15
|
+
* 检查是否有路径相同但方法不同的路由,以及潜在的路径冲突
|
|
16
|
+
*/
|
|
17
|
+
protected detectRouteConflicts(routes: any[]): void;
|
|
18
|
+
/**
|
|
19
|
+
* 检测动态路由的潜在冲突
|
|
20
|
+
*/
|
|
21
|
+
private detectDynamicRouteConflicts;
|
|
22
|
+
/**
|
|
23
|
+
* 判断两个路径是否可能冲突
|
|
24
|
+
*/
|
|
25
|
+
private pathsMayConflict;
|
|
26
|
+
/**
|
|
27
|
+
* 路径匹配
|
|
28
|
+
*/
|
|
29
|
+
protected matchPath(pattern: string, path: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 提取路径参数
|
|
32
|
+
*/
|
|
33
|
+
protected extractParams(pattern: string, path: string): Record<string, string>;
|
|
34
|
+
/**
|
|
35
|
+
* 处理 OPTIONS 请求
|
|
36
|
+
*/
|
|
37
|
+
protected handleOptions(pathname: string, routes: any[]): Response;
|
|
38
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 服务器基类
|
|
3
|
+
* 包含所有服务器类型的公共逻辑
|
|
4
|
+
*/
|
|
5
|
+
export class BaseServer {
|
|
6
|
+
globalMiddleware = [];
|
|
7
|
+
use(mw) {
|
|
8
|
+
this.globalMiddleware.push(mw);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 打印扁平化后的路由信息,用于调试
|
|
12
|
+
*/
|
|
13
|
+
logFlattenedRoutes(routes, type = "路由") {
|
|
14
|
+
console.log(`🚀 扁平化后的${type}:`);
|
|
15
|
+
for (const route of routes) {
|
|
16
|
+
const method = route.method || "GET";
|
|
17
|
+
const path = route.fullPath || route.path;
|
|
18
|
+
console.log(` ${method} ${path}`);
|
|
19
|
+
if (route.middlewareChain && route.middlewareChain.length > 0) {
|
|
20
|
+
console.log(` 中间件链: ${route.middlewareChain.length} 个`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
console.log("");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 检测路由冲突
|
|
27
|
+
* 检查是否有路径相同但方法不同的路由,以及潜在的路径冲突
|
|
28
|
+
*/
|
|
29
|
+
detectRouteConflicts(routes) {
|
|
30
|
+
const pathGroups = new Map();
|
|
31
|
+
// 按路径分组
|
|
32
|
+
for (const route of routes) {
|
|
33
|
+
const path = route.fullPath || route.path;
|
|
34
|
+
const method = route.method || "GET";
|
|
35
|
+
if (!pathGroups.has(path)) {
|
|
36
|
+
pathGroups.set(path, []);
|
|
37
|
+
}
|
|
38
|
+
pathGroups.get(path).push({ ...route, method });
|
|
39
|
+
}
|
|
40
|
+
// 检查冲突
|
|
41
|
+
for (const [path, routeList] of pathGroups) {
|
|
42
|
+
if (routeList.length > 1) {
|
|
43
|
+
const methods = routeList.map((r) => r.method);
|
|
44
|
+
const uniqueMethods = [...new Set(methods)];
|
|
45
|
+
if (uniqueMethods.length === 1) {
|
|
46
|
+
// 相同路径、相同方法 - 这是冲突!
|
|
47
|
+
console.warn(`⚠️ 路由冲突: ${uniqueMethods[0]} ${path} 定义了 ${routeList.length} 次`);
|
|
48
|
+
routeList.forEach((route, index) => {
|
|
49
|
+
console.warn(` ${index + 1}. ${route.method} ${path}`);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// 相同路径、不同方法 - 这是正常的
|
|
54
|
+
console.log(`ℹ️ 路径 ${path} 支持方法: ${uniqueMethods.join(", ")}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 检查潜在的路径冲突(动态路由可能冲突)
|
|
59
|
+
this.detectDynamicRouteConflicts(routes);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 检测动态路由的潜在冲突
|
|
63
|
+
*/
|
|
64
|
+
detectDynamicRouteConflicts(routes) {
|
|
65
|
+
const dynamicRoutes = routes.filter((r) => {
|
|
66
|
+
const path = r.fullPath || r.path;
|
|
67
|
+
return path.includes(":") || path.includes("*");
|
|
68
|
+
});
|
|
69
|
+
for (let i = 0; i < dynamicRoutes.length; i++) {
|
|
70
|
+
for (let j = i + 1; j < dynamicRoutes.length; j++) {
|
|
71
|
+
const route1 = dynamicRoutes[i];
|
|
72
|
+
const route2 = dynamicRoutes[j];
|
|
73
|
+
const method1 = route1.method || "GET";
|
|
74
|
+
const method2 = route2.method || "GET";
|
|
75
|
+
if (method1 === method2) {
|
|
76
|
+
const path1 = route1.fullPath || route1.path;
|
|
77
|
+
const path2 = route2.fullPath || route2.path;
|
|
78
|
+
// 检查路径是否可能冲突
|
|
79
|
+
if (this.pathsMayConflict(path1, path2)) {
|
|
80
|
+
console.warn(`⚠️ 潜在路由冲突: ${method1} ${path1} 可能与 ${path2} 冲突`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 判断两个路径是否可能冲突
|
|
88
|
+
*/
|
|
89
|
+
pathsMayConflict(path1, path2) {
|
|
90
|
+
const parts1 = path1.split("/").filter(Boolean);
|
|
91
|
+
const parts2 = path2.split("/").filter(Boolean);
|
|
92
|
+
if (parts1.length !== parts2.length)
|
|
93
|
+
return false;
|
|
94
|
+
for (let i = 0; i < parts1.length; i++) {
|
|
95
|
+
const p1 = parts1[i];
|
|
96
|
+
const p2 = parts2[i];
|
|
97
|
+
// 如果两个部分都是静态的且不同,则不会冲突
|
|
98
|
+
if (!p1.startsWith(":") &&
|
|
99
|
+
!p1.startsWith("*") &&
|
|
100
|
+
!p2.startsWith(":") &&
|
|
101
|
+
!p2.startsWith("*") &&
|
|
102
|
+
p1 !== p2) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
// 如果一个是通配符,另一个是动态参数,可能冲突
|
|
106
|
+
if ((p1 === "*" && p2.startsWith(":")) ||
|
|
107
|
+
(p2 === "*" && p1.startsWith(":"))) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 路径匹配
|
|
115
|
+
*/
|
|
116
|
+
matchPath(pattern, path) {
|
|
117
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
118
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
119
|
+
if (patternParts.length !== pathParts.length) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
123
|
+
if (patternParts[i] !== pathParts[i] && !patternParts[i].startsWith(":")) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 提取路径参数
|
|
131
|
+
*/
|
|
132
|
+
extractParams(pattern, path) {
|
|
133
|
+
const params = {};
|
|
134
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
135
|
+
const pathParts = path.split("/").filter(Boolean);
|
|
136
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
137
|
+
if (patternParts[i].startsWith(":")) {
|
|
138
|
+
const paramName = patternParts[i].slice(1);
|
|
139
|
+
params[paramName] = pathParts[i];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return params;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 处理 OPTIONS 请求
|
|
146
|
+
*/
|
|
147
|
+
handleOptions(pathname, routes) {
|
|
148
|
+
const availableMethods = [];
|
|
149
|
+
for (const route of routes) {
|
|
150
|
+
const path = route.fullPath || route.path;
|
|
151
|
+
const method = route.method || "GET";
|
|
152
|
+
if (this.matchPath(path, pathname)) {
|
|
153
|
+
availableMethods.push(method);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// 去重并排序
|
|
157
|
+
const uniqueMethods = [...new Set(availableMethods)].sort();
|
|
158
|
+
return new Response(null, {
|
|
159
|
+
status: 204,
|
|
160
|
+
headers: {
|
|
161
|
+
Allow: uniqueMethods.join(", "),
|
|
162
|
+
"Access-Control-Allow-Methods": uniqueMethods.join(", "),
|
|
163
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ComponentRoute, NestedComponentRoute } from "../types/component-route";
|
|
2
|
+
import { BaseServer } from "./base-server";
|
|
3
|
+
import { DependencyManager } from "../utils/dependency-manager";
|
|
4
|
+
/**
|
|
5
|
+
* 组件路由服务器
|
|
6
|
+
* 专门处理声明式组件路由
|
|
7
|
+
*/
|
|
8
|
+
export declare class ComponentServer extends BaseServer {
|
|
9
|
+
private routes;
|
|
10
|
+
private dependencyManager;
|
|
11
|
+
constructor(routes: (ComponentRoute | NestedComponentRoute)[]);
|
|
12
|
+
/**
|
|
13
|
+
* 处理请求
|
|
14
|
+
*/
|
|
15
|
+
fetch(req: Request): Promise<Response>;
|
|
16
|
+
/**
|
|
17
|
+
* 执行中间件链
|
|
18
|
+
*/
|
|
19
|
+
private executeMiddlewareChain;
|
|
20
|
+
/**
|
|
21
|
+
* 渲染 Vue 组件
|
|
22
|
+
*/
|
|
23
|
+
private renderVueComponent;
|
|
24
|
+
/**
|
|
25
|
+
* 渲染 React 组件
|
|
26
|
+
*/
|
|
27
|
+
private renderReactComponent;
|
|
28
|
+
/**
|
|
29
|
+
* 获取依赖管理器(用于外部访问)
|
|
30
|
+
*/
|
|
31
|
+
getDependencyManager(): DependencyManager;
|
|
32
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { flattenComponentRoutes } from "../middleware/component-router";
|
|
2
|
+
import { BaseServer } from "./base-server";
|
|
3
|
+
import { PathMatcher } from "../utils/path-matcher";
|
|
4
|
+
import { HtmlRenderer } from "../utils/html-renderer";
|
|
5
|
+
import { DependencyManager } from "../utils/dependency-manager";
|
|
6
|
+
/**
|
|
7
|
+
* 组件路由服务器
|
|
8
|
+
* 专门处理声明式组件路由
|
|
9
|
+
*/
|
|
10
|
+
export class ComponentServer extends BaseServer {
|
|
11
|
+
routes;
|
|
12
|
+
dependencyManager;
|
|
13
|
+
constructor(routes) {
|
|
14
|
+
super();
|
|
15
|
+
this.routes = flattenComponentRoutes(routes);
|
|
16
|
+
this.dependencyManager = new DependencyManager();
|
|
17
|
+
// 检测路由冲突
|
|
18
|
+
this.detectRouteConflicts(this.routes);
|
|
19
|
+
this.logFlattenedRoutes(this.routes, "组件路由");
|
|
20
|
+
console.log("🚀 依赖按需加载,服务器启动完成");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 处理请求
|
|
24
|
+
*/
|
|
25
|
+
async fetch(req) {
|
|
26
|
+
const url = new URL(req.url);
|
|
27
|
+
const pathname = url.pathname;
|
|
28
|
+
const method = req.method;
|
|
29
|
+
// 只支持 GET 请求
|
|
30
|
+
if (method !== "GET") {
|
|
31
|
+
return new Response("Method Not Allowed", { status: 405 });
|
|
32
|
+
}
|
|
33
|
+
// 查找匹配的路由
|
|
34
|
+
let matchedRoute = null;
|
|
35
|
+
for (const route of this.routes) {
|
|
36
|
+
if (PathMatcher.matchPath(route.fullPath, pathname)) {
|
|
37
|
+
matchedRoute = route;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!matchedRoute) {
|
|
42
|
+
return new Response("Not Found", { status: 404 });
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
// 创建中间件上下文
|
|
46
|
+
const context = {
|
|
47
|
+
req,
|
|
48
|
+
params: PathMatcher.extractParams(matchedRoute.fullPath, pathname),
|
|
49
|
+
query: Object.fromEntries(url.searchParams),
|
|
50
|
+
pathname,
|
|
51
|
+
};
|
|
52
|
+
// 执行中间件链,中间件会处理组件渲染
|
|
53
|
+
return await this.executeMiddlewareChain(matchedRoute.middlewareChain, context, matchedRoute.component);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error("组件渲染失败:", error);
|
|
57
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 执行中间件链
|
|
62
|
+
*/
|
|
63
|
+
async executeMiddlewareChain(middlewareChain, context, componentImport) {
|
|
64
|
+
// 创建最终的渲染函数
|
|
65
|
+
const renderComponent = async () => {
|
|
66
|
+
const componentModule = await componentImport();
|
|
67
|
+
const component = componentModule.default || componentModule;
|
|
68
|
+
// 自动检测组件类型
|
|
69
|
+
const componentType = this.dependencyManager.detectComponentType(component);
|
|
70
|
+
// 按需加载依赖
|
|
71
|
+
const deps = await this.dependencyManager.getFrameworkDeps(componentType);
|
|
72
|
+
// 根据组件类型渲染
|
|
73
|
+
if (componentType === "vue") {
|
|
74
|
+
return await this.renderVueComponent(component, context, deps);
|
|
75
|
+
}
|
|
76
|
+
else if (componentType === "react") {
|
|
77
|
+
return await this.renderReactComponent(component, context, deps);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
throw new Error(`不支持的组件类型: ${componentType}`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// 执行中间件链
|
|
84
|
+
let index = 0;
|
|
85
|
+
const next = async () => {
|
|
86
|
+
if (index >= middlewareChain.length) {
|
|
87
|
+
return await renderComponent();
|
|
88
|
+
}
|
|
89
|
+
const middleware = middlewareChain[index++];
|
|
90
|
+
return await middleware(context.req, next);
|
|
91
|
+
};
|
|
92
|
+
return await next();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 渲染 Vue 组件
|
|
96
|
+
*/
|
|
97
|
+
async renderVueComponent(component, context, deps) {
|
|
98
|
+
try {
|
|
99
|
+
const [vue, renderer] = deps;
|
|
100
|
+
const app = vue.createSSRApp(component);
|
|
101
|
+
// 提供路由信息
|
|
102
|
+
app.provide("routeInfo", {
|
|
103
|
+
params: context.params || {},
|
|
104
|
+
query: context.query || {},
|
|
105
|
+
pathname: context.pathname,
|
|
106
|
+
});
|
|
107
|
+
const html = await renderer.renderToString(app);
|
|
108
|
+
const fullHtml = HtmlRenderer.generateVueHtml(html, context);
|
|
109
|
+
return new Response(fullHtml, {
|
|
110
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error("Vue 组件渲染失败:", error);
|
|
115
|
+
return new Response("Vue Component Render Error", { status: 500 });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 渲染 React 组件
|
|
120
|
+
*/
|
|
121
|
+
async renderReactComponent(component, context, deps) {
|
|
122
|
+
try {
|
|
123
|
+
const [react, renderer] = deps;
|
|
124
|
+
const content = react.createElement(component, {
|
|
125
|
+
req: context.req,
|
|
126
|
+
params: context.params || {},
|
|
127
|
+
query: context.query || {},
|
|
128
|
+
});
|
|
129
|
+
const html = renderer.renderToString(content);
|
|
130
|
+
const fullHtml = HtmlRenderer.generateReactHtml(html, context);
|
|
131
|
+
return new Response(fullHtml, {
|
|
132
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error("React 组件渲染失败:", error);
|
|
137
|
+
return new Response("React Component Render Error", { status: 500 });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 获取依赖管理器(用于外部访问)
|
|
142
|
+
*/
|
|
143
|
+
getDependencyManager() {
|
|
144
|
+
return this.dependencyManager;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Server } from "./server";
|
|
2
|
+
export { ComponentServer } from "./component-server";
|
|
3
|
+
export { BaseServer } from "./base-server";
|
|
4
|
+
export { ServerFactory } from "./server-factory";
|
|
5
|
+
export { PathMatcher } from "../utils/path-matcher";
|
|
6
|
+
export { HtmlRenderer } from "../utils/html-renderer";
|
|
7
|
+
export { DependencyManager } from "../utils/dependency-manager";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// 导出所有服务器相关的类和工具
|
|
2
|
+
export { Server } from "./server";
|
|
3
|
+
export { ComponentServer } from "./component-server";
|
|
4
|
+
export { BaseServer } from "./base-server";
|
|
5
|
+
export { ServerFactory } from "./server-factory";
|
|
6
|
+
// 导出工具类
|
|
7
|
+
export { PathMatcher } from "../utils/path-matcher";
|
|
8
|
+
export { HtmlRenderer } from "../utils/html-renderer";
|
|
9
|
+
export { DependencyManager } from "../utils/dependency-manager";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Route, NestedRoute } from "../types";
|
|
2
|
+
import type { ComponentRoute, NestedComponentRoute } from "../types/component-route";
|
|
3
|
+
import { Server } from "../server";
|
|
4
|
+
import { ComponentServer } from "./component-server";
|
|
5
|
+
/**
|
|
6
|
+
* 服务器工厂类
|
|
7
|
+
* 用于创建和管理不同类型的服务器
|
|
8
|
+
*/
|
|
9
|
+
export declare class ServerFactory {
|
|
10
|
+
private servers;
|
|
11
|
+
/**
|
|
12
|
+
* 创建标准REST API服务器
|
|
13
|
+
*/
|
|
14
|
+
createRestServer(routes: (Route | NestedRoute)[]): Server;
|
|
15
|
+
/**
|
|
16
|
+
* 创建组件服务器
|
|
17
|
+
*/
|
|
18
|
+
createComponentServer(routes: (ComponentRoute | NestedComponentRoute)[]): ComponentServer;
|
|
19
|
+
/**
|
|
20
|
+
* 获取指定类型的服务器
|
|
21
|
+
*/
|
|
22
|
+
getServer(type: "rest" | "component"): Server | ComponentServer | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* 获取所有服务器
|
|
25
|
+
*/
|
|
26
|
+
getAllServers(): Map<string, Server | ComponentServer>;
|
|
27
|
+
/**
|
|
28
|
+
* 移除指定类型的服务器
|
|
29
|
+
*/
|
|
30
|
+
removeServer(type: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* 清除所有服务器
|
|
33
|
+
*/
|
|
34
|
+
clearServers(): void;
|
|
35
|
+
/**
|
|
36
|
+
* 获取服务器状态信息
|
|
37
|
+
*/
|
|
38
|
+
getServerStatus(): Record<string, {
|
|
39
|
+
type: string;
|
|
40
|
+
routes: number;
|
|
41
|
+
}>;
|
|
42
|
+
}
|