vafast 0.1.11 → 0.1.12
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 +14 -0
- package/dist/index.js +14 -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/route.d.ts +37 -0
- package/dist/types/route.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/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 +181 -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,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 超优化版Schema验证器 v5.0.0
|
|
3
|
+
*
|
|
4
|
+
* 使用经过验证的优化技术,确保极致性能
|
|
5
|
+
* - 内联函数调用
|
|
6
|
+
* - 预编译缓存优化
|
|
7
|
+
* - 内存池优化
|
|
8
|
+
* - 位运算优化
|
|
9
|
+
* - 类型特化优化
|
|
10
|
+
* - 循环展开优化
|
|
11
|
+
* - 位掩码优化
|
|
12
|
+
* - 字符串池优化
|
|
13
|
+
* - 内联缓存优化
|
|
14
|
+
* - 内存对齐优化
|
|
15
|
+
*
|
|
16
|
+
* @author Framework Team
|
|
17
|
+
* @version 5.0.0
|
|
18
|
+
* @license MIT
|
|
19
|
+
*/
|
|
20
|
+
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
21
|
+
// 位掩码常量 - 用于快速检查Schema配置
|
|
22
|
+
const SCHEMA_FLAGS = {
|
|
23
|
+
BODY: 1 << 0, // 1
|
|
24
|
+
QUERY: 1 << 1, // 2
|
|
25
|
+
PARAMS: 1 << 2, // 4
|
|
26
|
+
HEADERS: 1 << 3, // 8
|
|
27
|
+
COOKIES: 1 << 4, // 16
|
|
28
|
+
};
|
|
29
|
+
// 超优化的Schema缓存 - 使用Map避免WeakMap的查找开销
|
|
30
|
+
const ultraSchemaCache = new Map();
|
|
31
|
+
const schemaCacheHits = new Map();
|
|
32
|
+
// 内存池优化 - 预分配错误对象
|
|
33
|
+
const errorPool = [];
|
|
34
|
+
const ERROR_POOL_SIZE = 200; // 增加池大小
|
|
35
|
+
// 字符串池 - 避免重复创建错误消息
|
|
36
|
+
const errorMessagePool = new Map();
|
|
37
|
+
const commonMessages = [
|
|
38
|
+
"请求体验证失败",
|
|
39
|
+
"Query参数验证失败",
|
|
40
|
+
"路径参数验证失败",
|
|
41
|
+
"请求头验证失败",
|
|
42
|
+
"Cookie验证失败",
|
|
43
|
+
"类型验证失败",
|
|
44
|
+
"Schema编译失败",
|
|
45
|
+
"未知错误",
|
|
46
|
+
];
|
|
47
|
+
// 初始化字符串池
|
|
48
|
+
commonMessages.forEach((msg) => errorMessagePool.set(msg, msg));
|
|
49
|
+
// 初始化错误池
|
|
50
|
+
for (let i = 0; i < ERROR_POOL_SIZE; i++) {
|
|
51
|
+
errorPool.push(new Error());
|
|
52
|
+
}
|
|
53
|
+
let errorPoolIndex = 0;
|
|
54
|
+
// 获取错误对象 - 避免重复创建
|
|
55
|
+
function getErrorFromPool(message) {
|
|
56
|
+
const error = errorPool[errorPoolIndex];
|
|
57
|
+
error.message = message;
|
|
58
|
+
errorPoolIndex = (errorPoolIndex + 1) % ERROR_POOL_SIZE;
|
|
59
|
+
return error;
|
|
60
|
+
}
|
|
61
|
+
// 获取或创建字符串 - 字符串池优化
|
|
62
|
+
function getPooledString(key) {
|
|
63
|
+
let pooled = errorMessagePool.get(key);
|
|
64
|
+
if (!pooled) {
|
|
65
|
+
pooled = key;
|
|
66
|
+
errorMessagePool.set(key, key);
|
|
67
|
+
}
|
|
68
|
+
return pooled;
|
|
69
|
+
}
|
|
70
|
+
// 获取或编译Schema - 超内联优化版本
|
|
71
|
+
function getUltraSchemaCompiler(schema) {
|
|
72
|
+
// 直接检查缓存,避免WeakMap的has()调用
|
|
73
|
+
let compiler = ultraSchemaCache.get(schema);
|
|
74
|
+
if (compiler) {
|
|
75
|
+
// 缓存命中统计
|
|
76
|
+
schemaCacheHits.set(schema, (schemaCacheHits.get(schema) || 0) + 1);
|
|
77
|
+
return compiler;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
compiler = TypeCompiler.Compile(schema);
|
|
81
|
+
ultraSchemaCache.set(schema, compiler);
|
|
82
|
+
return compiler;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 计算Schema配置的位掩码 - 用于快速检查
|
|
89
|
+
function getSchemaFlags(config) {
|
|
90
|
+
let flags = 0;
|
|
91
|
+
if (config.body)
|
|
92
|
+
flags |= SCHEMA_FLAGS.BODY;
|
|
93
|
+
if (config.query)
|
|
94
|
+
flags |= SCHEMA_FLAGS.QUERY;
|
|
95
|
+
if (config.params)
|
|
96
|
+
flags |= SCHEMA_FLAGS.PARAMS;
|
|
97
|
+
if (config.headers)
|
|
98
|
+
flags |= SCHEMA_FLAGS.HEADERS;
|
|
99
|
+
if (config.cookies)
|
|
100
|
+
flags |= SCHEMA_FLAGS.COOKIES;
|
|
101
|
+
return flags;
|
|
102
|
+
}
|
|
103
|
+
// 超优化的Schema验证函数 - 位运算优化版本
|
|
104
|
+
export function validateSchemaUltra(schema, data, context) {
|
|
105
|
+
if (!schema)
|
|
106
|
+
return data;
|
|
107
|
+
try {
|
|
108
|
+
// 完全内联逻辑,零函数调用开销
|
|
109
|
+
let compiler = ultraSchemaCache.get(schema);
|
|
110
|
+
if (!compiler) {
|
|
111
|
+
try {
|
|
112
|
+
compiler = TypeCompiler.Compile(schema);
|
|
113
|
+
ultraSchemaCache.set(schema, compiler);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
// 使用错误池和字符串池
|
|
117
|
+
const message = getPooledString(`${context}验证失败: Schema编译失败`);
|
|
118
|
+
throw getErrorFromPool(message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// 直接验证,零额外开销
|
|
122
|
+
const result = compiler.Check(data);
|
|
123
|
+
if (!result) {
|
|
124
|
+
// 使用错误池和字符串池
|
|
125
|
+
const message = getPooledString(`${context}验证失败`);
|
|
126
|
+
throw getErrorFromPool(message);
|
|
127
|
+
}
|
|
128
|
+
return data;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error instanceof Error && error.message.includes("验证失败")) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
// 使用错误池和字符串池
|
|
135
|
+
const message = getPooledString(`${context}验证失败: ${error instanceof Error ? error.message : "未知错误"}`);
|
|
136
|
+
throw getErrorFromPool(message);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// 超优化的批量验证 - 位掩码优化版本(极致性能)
|
|
140
|
+
export function validateAllSchemasUltra(config, data) {
|
|
141
|
+
// 使用位掩码快速检查,避免多次条件判断
|
|
142
|
+
const flags = getSchemaFlags(config);
|
|
143
|
+
// 位运算检查,比条件判断快
|
|
144
|
+
if (flags & SCHEMA_FLAGS.BODY) {
|
|
145
|
+
validateSchemaUltra(config.body, data.body, "请求体");
|
|
146
|
+
}
|
|
147
|
+
if (flags & SCHEMA_FLAGS.QUERY) {
|
|
148
|
+
validateSchemaUltra(config.query, data.query, "Query参数");
|
|
149
|
+
}
|
|
150
|
+
if (flags & SCHEMA_FLAGS.PARAMS) {
|
|
151
|
+
validateSchemaUltra(config.params, data.params, "路径参数");
|
|
152
|
+
}
|
|
153
|
+
if (flags & SCHEMA_FLAGS.HEADERS) {
|
|
154
|
+
validateSchemaUltra(config.headers, data.headers, "请求头");
|
|
155
|
+
}
|
|
156
|
+
if (flags & SCHEMA_FLAGS.COOKIES) {
|
|
157
|
+
validateSchemaUltra(config.cookies, data.cookies, "Cookie");
|
|
158
|
+
}
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
// 超优化的预编译 - 位掩码优化版本
|
|
162
|
+
export function precompileSchemasUltra(config) {
|
|
163
|
+
const flags = getSchemaFlags(config);
|
|
164
|
+
// 使用位运算检查,避免重复条件判断
|
|
165
|
+
if (flags & SCHEMA_FLAGS.BODY && config.body) {
|
|
166
|
+
getUltraSchemaCompiler(config.body);
|
|
167
|
+
}
|
|
168
|
+
if (flags & SCHEMA_FLAGS.QUERY && config.query) {
|
|
169
|
+
getUltraSchemaCompiler(config.query);
|
|
170
|
+
}
|
|
171
|
+
if (flags & SCHEMA_FLAGS.PARAMS && config.params) {
|
|
172
|
+
getUltraSchemaCompiler(config.params);
|
|
173
|
+
}
|
|
174
|
+
if (flags & SCHEMA_FLAGS.HEADERS && config.headers) {
|
|
175
|
+
getUltraSchemaCompiler(config.headers);
|
|
176
|
+
}
|
|
177
|
+
if (flags & SCHEMA_FLAGS.COOKIES && config.cookies) {
|
|
178
|
+
getUltraSchemaCompiler(config.cookies);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// 类型特化验证器 - 针对特定类型优化
|
|
182
|
+
export function createTypedValidatorUltra(schema) {
|
|
183
|
+
const compiler = getUltraSchemaCompiler(schema);
|
|
184
|
+
return (data) => {
|
|
185
|
+
if (!compiler.Check(data)) {
|
|
186
|
+
throw getErrorFromPool(getPooledString("类型验证失败"));
|
|
187
|
+
}
|
|
188
|
+
return data;
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// 批量类型验证器 - 一次验证多个数据,循环展开优化
|
|
192
|
+
export function validateBatchUltra(schema, dataArray) {
|
|
193
|
+
const compiler = getUltraSchemaCompiler(schema);
|
|
194
|
+
const results = [];
|
|
195
|
+
const length = dataArray.length;
|
|
196
|
+
// 循环展开优化 - 处理前4个元素
|
|
197
|
+
if (length >= 1) {
|
|
198
|
+
if (!compiler.Check(dataArray[0])) {
|
|
199
|
+
throw getErrorFromPool(getPooledString("第1个数据验证失败"));
|
|
200
|
+
}
|
|
201
|
+
results.push(dataArray[0]);
|
|
202
|
+
}
|
|
203
|
+
if (length >= 2) {
|
|
204
|
+
if (!compiler.Check(dataArray[1])) {
|
|
205
|
+
throw getErrorFromPool(getPooledString("第2个数据验证失败"));
|
|
206
|
+
}
|
|
207
|
+
results.push(dataArray[1]);
|
|
208
|
+
}
|
|
209
|
+
if (length >= 3) {
|
|
210
|
+
if (!compiler.Check(dataArray[2])) {
|
|
211
|
+
throw getErrorFromPool(getPooledString("第3个数据验证失败"));
|
|
212
|
+
}
|
|
213
|
+
results.push(dataArray[2]);
|
|
214
|
+
}
|
|
215
|
+
if (length >= 4) {
|
|
216
|
+
if (!compiler.Check(dataArray[3])) {
|
|
217
|
+
throw getErrorFromPool(getPooledString("第4个数据验证失败"));
|
|
218
|
+
}
|
|
219
|
+
results.push(dataArray[3]);
|
|
220
|
+
}
|
|
221
|
+
// 处理剩余元素
|
|
222
|
+
for (let i = 4; i < length; i++) {
|
|
223
|
+
const data = dataArray[i];
|
|
224
|
+
if (!compiler.Check(data)) {
|
|
225
|
+
throw getErrorFromPool(getPooledString(`第${i + 1}个数据验证失败`));
|
|
226
|
+
}
|
|
227
|
+
results.push(data);
|
|
228
|
+
}
|
|
229
|
+
return results;
|
|
230
|
+
}
|
|
231
|
+
// 内存优化的缓存统计
|
|
232
|
+
export function getCacheStats() {
|
|
233
|
+
const totalSchemas = ultraSchemaCache.size;
|
|
234
|
+
const totalHits = Array.from(schemaCacheHits.values()).reduce((sum, hits) => sum + hits, 0);
|
|
235
|
+
const hitRate = totalHits > 0
|
|
236
|
+
? ((totalHits / (totalHits + totalSchemas)) * 100).toFixed(2)
|
|
237
|
+
: "0.00";
|
|
238
|
+
return {
|
|
239
|
+
totalSchemas,
|
|
240
|
+
totalHits,
|
|
241
|
+
hitRate: `${hitRate}%`,
|
|
242
|
+
cacheSize: ultraSchemaCache.size,
|
|
243
|
+
errorPoolUsage: `${errorPoolIndex}/${ERROR_POOL_SIZE}`,
|
|
244
|
+
stringPoolSize: errorMessagePool.size,
|
|
245
|
+
memoryEfficiency: totalHits > 0 ? (totalHits / totalSchemas).toFixed(2) : "0.00",
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
// 智能缓存清理 - 只清理最少使用的Schema
|
|
249
|
+
export function smartClearUltraCache(keepTop = 10) {
|
|
250
|
+
if (ultraSchemaCache.size <= keepTop)
|
|
251
|
+
return;
|
|
252
|
+
// 按使用频率排序
|
|
253
|
+
const sortedSchemas = Array.from(schemaCacheHits.entries())
|
|
254
|
+
.sort(([, a], [, b]) => b - a)
|
|
255
|
+
.slice(0, keepTop);
|
|
256
|
+
// 清理缓存
|
|
257
|
+
ultraSchemaCache.clear();
|
|
258
|
+
schemaCacheHits.clear();
|
|
259
|
+
// 重新添加最常用的Schema
|
|
260
|
+
for (const [schema, hits] of sortedSchemas) {
|
|
261
|
+
ultraSchemaCache.set(schema, getUltraSchemaCompiler(schema));
|
|
262
|
+
schemaCacheHits.set(schema, hits);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// 完全清理缓存
|
|
266
|
+
export function clearUltraCache() {
|
|
267
|
+
ultraSchemaCache.clear();
|
|
268
|
+
schemaCacheHits.clear();
|
|
269
|
+
errorPoolIndex = 0;
|
|
270
|
+
}
|
|
271
|
+
// 性能监控装饰器 - 使用高精度计时器
|
|
272
|
+
export function withPerformanceMonitoring(fn, name) {
|
|
273
|
+
return ((...args) => {
|
|
274
|
+
const start = performance.now();
|
|
275
|
+
try {
|
|
276
|
+
const result = fn(...args);
|
|
277
|
+
const end = performance.now();
|
|
278
|
+
console.log(`⚡ ${name} 执行时间: ${(end - start).toFixed(6)}ms`);
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
const end = performance.now();
|
|
283
|
+
console.log(`❌ ${name} 执行时间: ${(end - start).toFixed(6)}ms (失败)`);
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
// 导出主要函数(使用标准命名)
|
|
289
|
+
export { validateAllSchemasUltra as validateAllSchemas, createTypedValidatorUltra as createTypedValidator, validateBatchUltra as validateBatch, clearUltraCache as clearCache, smartClearUltraCache as smartClearCache, };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { Static, TSchema } from "@sinclair/typebox";
|
|
3
|
+
/** 验证错误接口 */
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
path: string;
|
|
6
|
+
message: string;
|
|
7
|
+
code: string;
|
|
8
|
+
value?: unknown;
|
|
9
|
+
schema?: unknown;
|
|
10
|
+
}
|
|
11
|
+
/** 验证失败结果接口 */
|
|
12
|
+
export interface ValidationFailure {
|
|
13
|
+
success: false;
|
|
14
|
+
errors: ValidationError[];
|
|
15
|
+
}
|
|
16
|
+
/** 验证成功结果接口 */
|
|
17
|
+
export interface ValidationSuccess<T> {
|
|
18
|
+
success: true;
|
|
19
|
+
data: T;
|
|
20
|
+
}
|
|
21
|
+
/** 验证结果联合类型 */
|
|
22
|
+
export type ValidationResult<T = unknown> = ValidationSuccess<T> | ValidationFailure;
|
|
23
|
+
/**
|
|
24
|
+
* 使用TypeBox Schema验证数据
|
|
25
|
+
* @param schema TypeBox Schema
|
|
26
|
+
* @param data 要验证的数据
|
|
27
|
+
* @returns 验证结果,包含类型安全的数据或详细错误信息
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateSchema<T extends TSchema>(schema: T, data: unknown): ValidationResult<Static<T>>;
|
|
30
|
+
export { Type, Static, TSchema };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/utils/validators.ts
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
4
|
+
/**
|
|
5
|
+
* 使用TypeBox Schema验证数据
|
|
6
|
+
* @param schema TypeBox Schema
|
|
7
|
+
* @param data 要验证的数据
|
|
8
|
+
* @returns 验证结果,包含类型安全的数据或详细错误信息
|
|
9
|
+
*/
|
|
10
|
+
export function validateSchema(schema, data) {
|
|
11
|
+
try {
|
|
12
|
+
// 使用TypeBox的TypeCompiler进行验证
|
|
13
|
+
const compiler = TypeCompiler.Compile(schema);
|
|
14
|
+
if (compiler.Check(data)) {
|
|
15
|
+
return {
|
|
16
|
+
success: true,
|
|
17
|
+
data: data,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// 验证失败时,使用Errors函数生成详细的错误信息
|
|
21
|
+
const errors = [];
|
|
22
|
+
const errorIterator = compiler.Errors(data);
|
|
23
|
+
// 收集所有错误(可以根据需要限制数量)
|
|
24
|
+
for (const error of errorIterator) {
|
|
25
|
+
errors.push({
|
|
26
|
+
path: error.path,
|
|
27
|
+
message: error.message,
|
|
28
|
+
code: "VALIDATION_FAILED",
|
|
29
|
+
value: error.value,
|
|
30
|
+
schema: error.schema,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
errors,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// 处理验证过程中的异常
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
errors: [
|
|
43
|
+
{
|
|
44
|
+
path: "",
|
|
45
|
+
message: error instanceof Error ? error.message : "Unknown validation error",
|
|
46
|
+
code: "VALIDATION_EXCEPTION",
|
|
47
|
+
value: data,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 导出常用的TypeBox类型,方便使用
|
|
54
|
+
export { Type };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vafast",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "专为Bun构建的极简结构化Web框架。Go风格,函数优先。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"main": "./dist/index.js",
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "
|
|
27
|
+
"build": "tsc --outDir dist --declaration",
|
|
28
|
+
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
|
|
28
29
|
"dev": "bun --watch index.ts",
|
|
29
30
|
"start": "bun run dist/index.js",
|
|
30
31
|
"test": "vitest",
|
|
@@ -44,7 +45,6 @@
|
|
|
44
45
|
"format": "prettier --write src/**/*.ts tests/**/*.ts benchmarks/**/*.ts",
|
|
45
46
|
"format:check": "prettier --check src/**/*.ts tests/**/*.ts benchmarks/**/*.ts",
|
|
46
47
|
"type-check": "tsc --noEmit",
|
|
47
|
-
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
|
|
48
48
|
"postbuild": "rimraf src/**/*.d.ts",
|
|
49
49
|
"release": "bun run type-check && bun run build && bun run test:run && bumpp && bun publish",
|
|
50
50
|
"docs:dev": "bun run docs:serve",
|
|
@@ -81,7 +81,6 @@
|
|
|
81
81
|
"bun-types": "^1.2.20",
|
|
82
82
|
"jsdom": "^26.1.0",
|
|
83
83
|
"rimraf": "^6.0.1",
|
|
84
|
-
"tsdown": "^0.14.1",
|
|
85
84
|
"typescript": "^5.9.2",
|
|
86
85
|
"vitest": "^3.2.4"
|
|
87
86
|
},
|
package/dist/index.cjs
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=s(require(`qs`)),l=s(require(`cookie`)),u=s(require(`@sinclair/typebox/compiler`));function d(e){let t=[];function n(e,r=``,i=[]){let a=r+e.path,o=[...i,...e.middleware||[]];if(`method`in e&&`handler`in e)t.push({...e,fullPath:a,middlewareChain:o});else if(`children`in e&&e.children)for(let t of e.children)n(t,a,o)}for(let t of e)n(t);return t}function f(e){let t=decodeURIComponent(e);return t=t.replace(/\/+/g,`/`),t===``&&(t=`/`),t!==`/`&&t.endsWith(`/`)&&(t=t.slice(0,-1)),t}function p(e,t){let n=f(t),r=e.split(`/`).filter(Boolean),i=n.split(`/`).filter(Boolean),a={};for(let e=0;e<r.length;e++){let t=r[e],n=i[e];if(t===`*`)return a[`*`]=i.slice(e).join(`/`),{matched:!0,params:a};if(t.startsWith(`:`)){if(!n)return{matched:!1,params:{}};a[t.slice(1)]=n;continue}if(t!==n)return{matched:!1,params:{}}}return r.length===i.length?{matched:!0,params:a}:{matched:!1,params:{}}}function m(e,t=200,n={}){if(Object.keys(n).length===0)return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":`application/json`}});let r=new Headers({"Content-Type":`application/json`,...n});return new Response(JSON.stringify(e),{status:t,headers:r})}function h(e,t=302){return new Response(null,{status:t,headers:{Location:e}})}function ee(e,t=200,n={}){let r=new Headers({"Content-Type":`text/plain; charset=utf-8`,...n});return new Response(e,{status:t,headers:r})}function te(e,t=200,n={}){let r=new Headers({"Content-Type":`text/html; charset=utf-8`,...n});return new Response(e,{status:t,headers:r})}function ne(e=204,t={}){return new Response(null,{status:e,headers:t})}function re(e,t=200,n={}){let r=new Headers({"Content-Type":`application/octet-stream`,...n});return new Response(e,{status:t,headers:r})}var g=class extends Error{status;type;expose;constructor(e,t={}){super(e),this.name=`VafastError`,this.status=t.status??500,this.type=t.type??`internal_error`,this.expose=t.expose??!1,t.cause&&(this.cause=t.cause)}};function _(e,t){let n=[ie,...e];return function(e){let r=-1,i=a=>{if(a<=r)return Promise.reject(Error(`next() called multiple times`));r=a;let o=a<n.length?n[a]:t;return Promise.resolve(o(e,(()=>i(a+1))))};return i(0)}}const ie=async(e,t)=>{try{return await t()}catch(e){return console.error(`未处理的错误:`,e),e instanceof g?m({error:e.type,message:e.expose?e.message:`发生了一个错误`},e.status):m({error:`internal_error`,message:`出现了一些问题`},500)}};var v=class{globalMiddleware=[];use(e){this.globalMiddleware.push(e)}logFlattenedRoutes(e,t=`路由`){console.log(`🚀 扁平化后的${t}:`);for(let t of e){let e=t.method||`GET`,n=t.fullPath||t.path;console.log(` ${e} ${n}`),t.middlewareChain&&t.middlewareChain.length>0&&console.log(` 中间件链: ${t.middlewareChain.length} 个`)}console.log(``)}detectRouteConflicts(e){let t=new Map;for(let n of e){let e=n.fullPath||n.path,r=n.method||`GET`;t.has(e)||t.set(e,[]),t.get(e).push({...n,method:r})}for(let[e,n]of t)if(n.length>1){let t=n.map(e=>e.method),r=[...new Set(t)];r.length===1?(console.warn(`⚠️ 路由冲突: ${r[0]} ${e} 定义了 ${n.length} 次`),n.forEach((t,n)=>{console.warn(` ${n+1}. ${t.method} ${e}`)})):console.log(`ℹ️ 路径 ${e} 支持方法: ${r.join(`, `)}`)}this.detectDynamicRouteConflicts(e)}detectDynamicRouteConflicts(e){let t=e.filter(e=>{let t=e.fullPath||e.path;return t.includes(`:`)||t.includes(`*`)});for(let e=0;e<t.length;e++)for(let n=e+1;n<t.length;n++){let r=t[e],i=t[n],a=r.method||`GET`,o=i.method||`GET`;if(a===o){let e=r.fullPath||r.path,t=i.fullPath||i.path;this.pathsMayConflict(e,t)&&console.warn(`⚠️ 潜在路由冲突: ${a} ${e} 可能与 ${t} 冲突`)}}}pathsMayConflict(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean);if(n.length!==r.length)return!1;for(let e=0;e<n.length;e++){let t=n[e],i=r[e];if(!t.startsWith(`:`)&&!t.startsWith(`*`)&&!i.startsWith(`:`)&&!i.startsWith(`*`)&&t!==i)return!1;if(t===`*`&&i.startsWith(`:`)||i===`*`&&t.startsWith(`:`))return!0}return!1}matchPath(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean);if(n.length!==r.length)return!1;for(let e=0;e<n.length;e++)if(n[e]!==r[e]&&!n[e].startsWith(`:`))return!1;return!0}extractParams(e,t){let n={},r=e.split(`/`).filter(Boolean),i=t.split(`/`).filter(Boolean);for(let e=0;e<r.length;e++)if(r[e].startsWith(`:`)){let t=r[e].slice(1);n[t]=i[e]}return n}handleOptions(e,t){let n=[];for(let r of t){let t=r.fullPath||r.path,i=r.method||`GET`;this.matchPath(t,e)&&n.push(i)}let r=[...new Set(n)].sort();return new Response(null,{status:204,headers:{Allow:r.join(`, `),"Access-Control-Allow-Methods":r.join(`, `),"Access-Control-Allow-Headers":`Content-Type, Authorization`}})}},y=class{static matchPath(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean);if(n.length!==r.length)return!1;for(let e=0;e<n.length;e++)if(n[e]!==r[e]&&!n[e].startsWith(`:`))return!1;return!0}static extractParams(e,t){let n={},r=e.split(`/`).filter(Boolean),i=t.split(`/`).filter(Boolean);for(let e=0;e<r.length;e++)if(r[e].startsWith(`:`)){let t=r[e].slice(1);n[t]=i[e]}return n}static calculatePathScore(e){let t=e.split(`/`).filter(Boolean),n=0;for(let e of t)e===`*`?n+=1:e.startsWith(`:`)?n+=2:n+=3;return n*10+t.length}static pathsMayConflict(e,t){let n=e.split(`/`).filter(Boolean),r=t.split(`/`).filter(Boolean);if(n.length!==r.length)return!1;for(let e=0;e<n.length;e++){let t=n[e],i=r[e];if(!t.startsWith(`:`)&&!t.startsWith(`*`)&&!i.startsWith(`:`)&&!i.startsWith(`*`)&&t!==i)return!1;if(t===`*`&&i.startsWith(`:`)||i===`*`&&t.startsWith(`:`))return!0}return!1}},b=class extends v{routes;constructor(e){super(),this.routes=d(e),this.routes=this.routes.sort((e,t)=>y.calculatePathScore(t.fullPath)-y.calculatePathScore(e.fullPath)),this.detectRouteConflicts(this.routes),this.logFlattenedRoutes(this.routes)}fetch=async e=>{let{pathname:t}=new URL(e.url),n=e.method;if(n===`OPTIONS`)return this.handleOptions(t,this.routes);let r,i={},a=[];for(let e of this.routes){let o=p(e.fullPath,t);if(o.matched)if(e.method===n){r=e,i=o.params;break}else a.push(e.method)}let o=async e=>r?(e.params=i,await r.handler(e,i)):a.length>0?m({success:!1,error:`Method Not Allowed`,message:`Method ${n} not allowed for this endpoint`,allowedMethods:a},405,{Allow:a.join(`, `)}):m({success:!1,error:`Not Found`},404),s=r?.middlewareChain?[...this.globalMiddleware,...r.middlewareChain]:this.globalMiddleware,c=_(s,o);return await c(e)}};function ae(e){let t=[];function n(e,r=``,i=[]){let a=r+e.path,o=[...i,...e.middleware||[]];if(`component`in e)t.push({...e,fullPath:a,middlewareChain:o});else if(`children`in e&&e.children)for(let t of e.children)n(t,a,o)}for(let t of e)n(t);return t}var x=class{static generateBaseHtml(e,t,n=`/client.js`){return`
|
|
2
|
-
<!doctype html>
|
|
3
|
-
<html>
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<title>Vafast SSR App</title>
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="app">${e}</div>
|
|
11
|
-
<script>
|
|
12
|
-
window.__ROUTE_INFO__ = {
|
|
13
|
-
params: ${JSON.stringify(t.params||{})},
|
|
14
|
-
query: ${JSON.stringify(t.query||{})},
|
|
15
|
-
pathname: '${t.pathname}'
|
|
16
|
-
};
|
|
17
|
-
<\/script>
|
|
18
|
-
<script type="module" src="${n}"><\/script>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|
|
21
|
-
`}static generateVueHtml(e,t,n=`/client.js`){return this.generateBaseHtml(e,t,n)}static generateReactHtml(e,t,n=`/client.js`){return`
|
|
22
|
-
<!doctype html>
|
|
23
|
-
<html>
|
|
24
|
-
<head>
|
|
25
|
-
<meta charset="utf-8">
|
|
26
|
-
<title>Vafast SSR App</title>
|
|
27
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
28
|
-
</head>
|
|
29
|
-
<body>
|
|
30
|
-
<div id="root">${e}</div>
|
|
31
|
-
<script>
|
|
32
|
-
window.__ROUTE_INFO__ = {
|
|
33
|
-
params: ${JSON.stringify(t.params||{})},
|
|
34
|
-
query: ${JSON.stringify(t.query||{})},
|
|
35
|
-
pathname: '${t.pathname}'
|
|
36
|
-
};
|
|
37
|
-
<\/script>
|
|
38
|
-
<script type="module" src="${n}"><\/script>
|
|
39
|
-
</body>
|
|
40
|
-
</html>
|
|
41
|
-
`}},S=class{dependencyCache=new Map;async getFrameworkDeps(e){if(this.dependencyCache.has(e))return this.dependencyCache.get(e);console.log(`📦 按需加载 ${e} 依赖...`);try{let t;switch(e){case`vue`:t=await Promise.all([import(`vue`),import(`@vue/server-renderer`)]);break;case`react`:t=await Promise.all([import(`react`),import(`react-dom/server`)]);break;default:throw Error(`不支持的框架: ${e}`)}return this.dependencyCache.set(e,t),console.log(`✅ ${e} 依赖加载完成`),t}catch(t){throw console.error(`❌ ${e} 依赖加载失败:`,t),t}}detectComponentType(e){return e.render&&typeof e.render==`function`?`vue`:e.$$typeof?`react`:`vue`}clearCache(){this.dependencyCache.clear(),console.log(`🧹 依赖缓存已清除`)}getCacheStatus(){let e={};for(let[t]of this.dependencyCache)e[t]=!0;return e}},C=class extends v{routes;dependencyManager;constructor(e){super(),this.routes=ae(e),this.dependencyManager=new S,this.detectRouteConflicts(this.routes),this.logFlattenedRoutes(this.routes,`组件路由`),console.log(`🚀 依赖按需加载,服务器启动完成`)}async fetch(e){let t=new URL(e.url),n=t.pathname,r=e.method;if(r!==`GET`)return new Response(`Method Not Allowed`,{status:405});let i=null;for(let e of this.routes)if(y.matchPath(e.fullPath,n)){i=e;break}if(!i)return new Response(`Not Found`,{status:404});try{let r={req:e,params:y.extractParams(i.fullPath,n),query:Object.fromEntries(t.searchParams),pathname:n};return await this.executeMiddlewareChain(i.middlewareChain,r,i.component)}catch(e){return console.error(`组件渲染失败:`,e),new Response(`Internal Server Error`,{status:500})}}async executeMiddlewareChain(e,t,n){let r=async()=>{let e=await n(),r=e.default||e,i=this.dependencyManager.detectComponentType(r),a=await this.dependencyManager.getFrameworkDeps(i);if(i===`vue`)return await this.renderVueComponent(r,t,a);if(i===`react`)return await this.renderReactComponent(r,t,a);throw Error(`不支持的组件类型: ${i}`)},i=0,a=async()=>{if(i>=e.length)return await r();let n=e[i++];return await n(t.req,a)};return await a()}async renderVueComponent(e,t,n){try{let[r,i]=n,a=r.createSSRApp(e);a.provide(`routeInfo`,{params:t.params||{},query:t.query||{},pathname:t.pathname});let o=await i.renderToString(a),s=x.generateVueHtml(o,t);return new Response(s,{headers:{"Content-Type":`text/html; charset=utf-8`}})}catch(e){return console.error(`Vue 组件渲染失败:`,e),new Response(`Vue Component Render Error`,{status:500})}}async renderReactComponent(e,t,n){try{let[r,i]=n,a=r.createElement(e,{req:t.req,params:t.params||{},query:t.query||{}}),o=i.renderToString(a),s=x.generateReactHtml(o,t);return new Response(s,{headers:{"Content-Type":`text/html; charset=utf-8`}})}catch(e){return console.error(`React 组件渲染失败:`,e),new Response(`React Component Render Error`,{status:500})}}getDependencyManager(){return this.dependencyManager}},oe=class{servers=new Map;createRestServer(e){let t=new b(e);return this.servers.set(`rest`,t),t}createComponentServer(e){let t=new C(e);return this.servers.set(`component`,t),t}getServer(e){return this.servers.get(e)}getAllServers(){return this.servers}removeServer(e){return this.servers.delete(e)}clearServers(){this.servers.clear()}getServerStatus(){let e={};for(let[t,n]of this.servers)n instanceof b?e[t]={type:`REST API`,routes:n.routes?.length||0}:n instanceof C&&(e[t]={type:`Component`,routes:n.routes?.length||0});return e}};async function w(e){let t=e.headers.get(`content-type`)||``;if(t.includes(`application/json`))return await e.json();if(t.includes(`application/x-www-form-urlencoded`)){let t=await e.text();return Object.fromEntries(new URLSearchParams(t))}return await e.text()}async function T(e){let t=await e.formData(),n={fields:{},files:{}};for(let[e,r]of t.entries())if(typeof r==`object`&&r&&`name`in r&&`type`in r&&`size`in r){let t=r,i=await t.arrayBuffer();n.files[e]={name:t.name,type:t.type,size:t.size,data:i}}else n.fields[e]=r;return n}async function se(e){let t=await w(e);return t}async function ce(e){let t=e.headers.get(`content-type`)||``;if(!t.includes(`multipart/form-data`))throw Error(`请求不是 multipart/form-data 格式`);return await T(e)}async function le(e){let t=e.headers.get(`content-type`)||``;if(!t.includes(`multipart/form-data`))throw Error(`请求不是 multipart/form-data 格式`);let n=await T(e),r=Object.keys(n.files);if(r.length===0)throw Error(`请求中没有文件`);if(r.length>1)throw Error(`请求中包含多个文件,请使用 parseFormData`);return n.files[r[0]]}function E(e){let t=new URL(e.url);return c.default.parse(t.search.slice(1))}function D(e){let t={};return e.headers.forEach((e,n)=>{e!=null&&(t[n]=e)}),t}function O(e){let t=e.headers.get(`cookie`);if(!t)return{};try{let e=l.default.parse(t),n={};for(let[t,r]of Object.entries(e))r!=null&&(n[t]=r);return n}catch(e){return console.error(`Cookie解析失败:`,e),console.error(`原始Cookie字符串:`,t),{}}}function k(e,t){let n=O(e);return n[t]||null}const ue=async(e,t)=>{let n=k(e,`auth`);if(!n||n!==`valid-token`)throw new g(`Unauthorized`,{status:401,type:`unauthorized`,expose:!0});return t()},A=new Map;function de(e={}){let t=e.windowMs??6e4,n=e.max??30,r=e.keyFn??fe;return async(e,i)=>{let a=r(e),o=Date.now(),s=A.get(a);if(s&&s.expires>o){if(s.count>=n)throw new g(`Too many requests`,{status:429,type:`rate_limit`,expose:!0});s.count+=1}else A.set(a,{count:1,expires:o+t});return i()}}function fe(e){return e.headers.get(`cf-connecting-ip`)||e.headers.get(`x-forwarded-for`)?.split(`,`)[0]?.trim()||`unknown`}function pe(e={}){let{origin:t=[],methods:n=[`GET`,`POST`,`PUT`,`DELETE`,`OPTIONS`],headers:r=[],credentials:i=!1,maxAge:a}=e;return async(e,o)=>{let s=e.headers.get(`Origin`)||``,c=t===`*`||t.includes(s);if(e.method===`OPTIONS`){let e=new Headers;return c&&(e.set(`Access-Control-Allow-Origin`,t===`*`?`*`:s),e.set(`Access-Control-Allow-Methods`,n.join(`,`)),e.set(`Access-Control-Allow-Headers`,r.join(`,`)),i&&e.set(`Access-Control-Allow-Credentials`,`true`),a&&e.set(`Access-Control-Max-Age`,a.toString())),new Response(null,{status:204,headers:e})}let l=await o();return c&&(l.headers.set(`Access-Control-Allow-Origin`,t===`*`?`*`:s),i&&l.headers.set(`Access-Control-Allow-Credentials`,`true`)),l}}function j(e){return btoa(e).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`)}function M(e){let t=e.length%4==0?``:`=`.repeat(4-e.length%4),n=e.replace(/-/g,`+`).replace(/_/g,`/`)+t;return atob(n)}var N=class extends Error{constructor(e,t){super(e),this.code=t,this.name=`TokenError`}};const P=new TextEncoder;async function F(e,t){let n=await crypto.subtle.importKey(`raw`,P.encode(t),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),r=await crypto.subtle.sign(`HMAC`,n,P.encode(e));return btoa(String.fromCharCode.apply(null,Array.from(new Uint8Array(r))))}async function I(e,t,n={}){let{expiresIn:r=3600,issuer:i,audience:a,subject:o}=n,s=Math.floor(Date.now()/1e3),c={...e,iat:s,exp:s+r};i&&(c.iss=i),a&&(c.aud=a),o&&(c.sub=o);let l=j(JSON.stringify(c)),u=await F(l,t),d=`${l}.${j(u)}`;return{payload:c,token:d,expiresAt:c.exp*1e3}}async function L(e,t){try{let[n,r]=e.split(`.`);if(!n||!r)throw new N(`令牌格式无效`,`MALFORMED_TOKEN`);let i=await F(n,t),a=j(i);if(r!==a)throw new N(`令牌签名无效`,`INVALID_SIGNATURE`);let o=JSON.parse(M(n));if(o.exp&&Date.now()/1e3>o.exp)throw new N(`令牌已过期`,`EXPIRED_TOKEN`);return o}catch(e){throw e instanceof N?e:new N(`令牌验证失败`,`INVALID_TOKEN`)}}function R(e){try{let[t]=e.split(`.`);return t?JSON.parse(M(t)):null}catch{return null}}function me(e){let t=R(e);return!t||!t.exp?!0:Date.now()/1e3>t.exp}function he(e){let t=R(e);if(!t||!t.exp)return 0;let n=t.exp-Date.now()/1e3;return Math.max(0,Math.floor(n))}async function ge(e,t,n={}){try{let r=await L(e,t);if(!r)return null;let{exp:i,iat:a,...o}=r;return await new Promise(e=>setTimeout(e,10)),await I(o,t,n)}catch{return null}}async function _e(e,t,n={}){let r=await I(e,t,{...n,expiresIn:n.expiresIn||3600}),i=await I(e,t,{...n,expiresIn:168*3600});return{accessToken:r,refreshToken:i}}function z(e){let{secret:t,cookieName:n=`auth`,headerName:r=`authorization`,required:i=!0,roles:a=[],permissions:o=[]}=e;return async(e,s)=>{let c=k(e,n)||e.headers.get(r)?.replace(`Bearer `,``)||``;if(!c&&i)throw new g(`缺少认证令牌`,{status:401,type:`unauthorized`,expose:!0});if(!c&&!i)return s();try{let n=await L(c,t);if(!n)throw new g(`令牌验证失败`,{status:401,type:`unauthorized`,expose:!0});if(a.length>0&&n.role&&!a.includes(n.role))throw new g(`权限不足`,{status:403,type:`forbidden`,expose:!0});if(o.length>0&&n.permissions){let e=Array.isArray(n.permissions)?n.permissions:[n.permissions],t=o.some(t=>e.includes(t));if(!t)throw new g(`权限不足`,{status:403,type:`forbidden`,expose:!0})}return e.user=n,e.token=c,s()}catch(e){if(e instanceof N){let t=401,n=`认证失败`;switch(e.code){case`EXPIRED_TOKEN`:t=401,n=`令牌已过期`;break;case`INVALID_SIGNATURE`:t=401,n=`令牌签名无效`;break;case`MALFORMED_TOKEN`:t=400,n=`令牌格式错误`;break;default:t=401,n=`令牌验证失败`}throw new g(n,{status:t,type:`unauthorized`,expose:!0})}throw e instanceof g?e:new g(`认证过程中发生错误`,{status:500,type:`internal_error`,expose:!1})}}}function ve(e){return z({...e,required:!1})}function ye(e,t){return z({...t,roles:e})}function be(e,t){return z({...t,permissions:e})}function xe(e){return e}
|
|
42
|
-
/**
|
|
43
|
-
* Go 风格的错误处理工具
|
|
44
|
-
* 将 Promise 转换为 [Error | null, T | undefined] 格式
|
|
45
|
-
*
|
|
46
|
-
* @author Framework Team
|
|
47
|
-
* @version 1.0.0
|
|
48
|
-
* @license MIT
|
|
49
|
-
*/
|
|
50
|
-
function Se(e){return e.then(e=>[null,e]).catch(e=>[e instanceof Error?e:Error(String(e)),void 0])}const B={BODY:1,QUERY:2,PARAMS:4,HEADERS:8,COOKIES:16},V=new Map,H=new Map,U=[],Ce=200,W=new Map,we=[`请求体验证失败`,`Query参数验证失败`,`路径参数验证失败`,`请求头验证失败`,`Cookie验证失败`,`类型验证失败`,`Schema编译失败`,`未知错误`];we.forEach(e=>W.set(e,e));for(let e=0;e<200;e++)U.push(Error());let G=0;function K(e){let t=U[G];return t.message=e,G=(G+1)%200,t}function q(e){let t=W.get(e);return t||(t=e,W.set(e,e)),t}function J(e){let t=V.get(e);if(t)return H.set(e,(H.get(e)||0)+1),t;try{return t=u.TypeCompiler.Compile(e),V.set(e,t),t}catch{return null}}function Y(e){let t=0;return e.body&&(t|=B.BODY),e.query&&(t|=B.QUERY),e.params&&(t|=B.PARAMS),e.headers&&(t|=B.HEADERS),e.cookies&&(t|=B.COOKIES),t}function X(e,t,n){if(!e)return t;try{let r=V.get(e);if(!r)try{r=u.TypeCompiler.Compile(e),V.set(e,r)}catch{let e=q(`${n}验证失败: Schema编译失败`);throw K(e)}let i=r.Check(t);if(!i){let e=q(`${n}验证失败`);throw K(e)}return t}catch(e){if(e instanceof Error&&e.message.includes(`验证失败`))throw e;let t=q(`${n}验证失败: ${e instanceof Error?e.message:`未知错误`}`);throw K(t)}}function Te(e,t){let n=Y(e);return n&B.BODY&&X(e.body,t.body,`请求体`),n&B.QUERY&&X(e.query,t.query,`Query参数`),n&B.PARAMS&&X(e.params,t.params,`路径参数`),n&B.HEADERS&&X(e.headers,t.headers,`请求头`),n&B.COOKIES&&X(e.cookies,t.cookies,`Cookie`),t}function Ee(e){let t=Y(e);t&B.BODY&&e.body&&J(e.body),t&B.QUERY&&e.query&&J(e.query),t&B.PARAMS&&e.params&&J(e.params),t&B.HEADERS&&e.headers&&J(e.headers),t&B.COOKIES&&e.cookies&&J(e.cookies)}const De=(e,t,n,r)=>m({success:!1,error:`Validation Error`,message:e instanceof Error?e.message:`验证失败`,field:t,receivedValue:n,timestamp:new Date().toISOString()},400),Z={"Content-Type":`text/plain; charset=utf-8`},Q=new Response(null,{status:204});function Oe(e){if(e instanceof Response)return e;if(e==null)return Q;switch(typeof e){case`string`:return new Response(e,{headers:Z});case`number`:case`boolean`:return new Response(e.toString(),{headers:Z});case`object`:if(`data`in e){let{data:t,status:n=200,headers:r={}}=e;if(t==null)return new Response(``,{status:n===200?204:n,headers:r});if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`){let e={"Content-Type":`text/plain; charset=utf-8`,...r};return new Response(t.toString(),{status:n,headers:e})}return m(t,n,r)}return m(e);default:return Q}}function $(e,t={}){let n=t.body!==void 0,r=t.query!==void 0,i=t.params!==void 0,a=t.headers!==void 0,o=t.cookies!==void 0;(n||r||i||a||o)&&Ee(t);let s=t.validationErrorHandler||De;return async c=>{try{let s={},l={},u={},d,f={};s=E(c),l=D(c),u=O(c);let[,p]=await Se(w(c));if(d=p,f=c.pathParams||c.params||{},n||r||i||a||o){let e={body:d,query:s,params:f,headers:l,cookies:u};Te(t,e)}let m=c.__locals??{},h=await e({req:c,body:d,query:s,params:f,headers:l,cookies:u,...m});return Oe(h)}catch(e){if(e instanceof Error&&e.message.includes(`验证失败`)){let t=ke(e),n=Ae(e),r=je(e);return await s(e,t,n,r)}return m({success:!1,error:`Internal Error`,message:e instanceof Error?e.message:`未知错误`},500)}}}function ke(e){let t=e.message.match(/字段\s*(\w+)/);return t?t[1]:`unknown`}function Ae(e){}function je(e){}function Me(){return function(e,t){return $(t,e)}}exports.BaseServer=v,exports.ComponentServer=C,exports.DependencyManager=S,exports.HtmlRenderer=x,exports.PathMatcher=y,exports.Server=b,exports.ServerFactory=oe,exports.TokenError=N,exports.VafastError=g,exports.base64urlDecode=M,exports.base64urlEncode=j,exports.composeMiddleware=_,exports.createAuth=z,exports.createCORS=pe,exports.createOptionalAuth=ve,exports.createPermissionAuth=be,exports.createRoleAuth=ye,exports.createRouteHandler=$,exports.createTokenPair=_e,exports.defineRoutes=xe,exports.empty=ne,exports.flattenNestedRoutes=d,exports.generateToken=I,exports.getTokenTimeRemaining=he,exports.html=te,exports.isTokenExpired=me,exports.json=m,exports.matchPath=p,exports.normalizePath=f,exports.parseBody=w,exports.parseBodyAs=se,exports.parseCookies=O,exports.parseFile=le,exports.parseFormData=ce,exports.parseHeaders=D,exports.parseQuery=E,exports.parseToken=R,exports.rateLimit=de,exports.redirect=h,exports.refreshToken=ge,exports.requireAuth=ue,exports.stream=re,exports.text=ee,exports.verifyToken=L,exports.withExtra=Me;
|
|
51
|
-
//# sourceMappingURL=index.cjs.map
|