vafast 0.3.7 → 0.3.10
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/README.md +45 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +190 -227
- package/dist/index.js.map +1 -1
- package/dist/utils/create-handler.js +34 -146
- package/dist/utils/create-handler.js.map +1 -1
- package/dist/utils/formats.d.ts +40 -0
- package/dist/utils/formats.js +116 -0
- package/dist/utils/formats.js.map +1 -0
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +187 -226
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/request-validator.d.ts +1 -1
- package/dist/utils/request-validator.js +26 -112
- package/dist/utils/request-validator.js.map +1 -1
- package/dist/utils/validators/validators.d.ts +44 -36
- package/dist/utils/validators/validators.js +43 -39
- package/dist/utils/validators/validators.js.map +1 -1
- package/package.json +6 -24
- package/dist/utils/validators/schema-validator.d.ts +0 -70
- package/dist/utils/validators/schema-validator.js +0 -241
- package/dist/utils/validators/schema-validator.js.map +0 -1
- package/dist/utils/validators/schema-validators-ultra.d.ts +0 -54
- package/dist/utils/validators/schema-validators-ultra.js +0 -266
- package/dist/utils/validators/schema-validators-ultra.js.map +0 -1
package/README.md
CHANGED
|
@@ -445,6 +445,51 @@ precompileSchemas([UserSchema, PostSchema, CommentSchema]);
|
|
|
445
445
|
|
|
446
446
|
**性能效果:首次编译后,10000 次验证仅需 ~5ms**
|
|
447
447
|
|
|
448
|
+
### 内置 Format 验证器
|
|
449
|
+
|
|
450
|
+
Vafast 内置 30+ 常用 format 验证器,**导入框架时自动注册**,对标 Zod 的内置验证:
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
import { Type, createHandler } from 'vafast';
|
|
454
|
+
|
|
455
|
+
// 直接使用内置 format,无需手动注册
|
|
456
|
+
const UserSchema = Type.Object({
|
|
457
|
+
email: Type.String({ format: 'email' }),
|
|
458
|
+
phone: Type.String({ format: 'phone' }), // 中国手机号
|
|
459
|
+
website: Type.String({ format: 'url' }),
|
|
460
|
+
avatar: Type.String({ format: 'uuid' }),
|
|
461
|
+
createdAt: Type.String({ format: 'date-time' }),
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const handler = createHandler({ body: UserSchema }, ({ body }) => {
|
|
465
|
+
return { success: true, user: body };
|
|
466
|
+
});
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**支持的 Format 列表:**
|
|
470
|
+
|
|
471
|
+
| 分类 | Format | 说明 |
|
|
472
|
+
|------|--------|------|
|
|
473
|
+
| **标识符** | `email`, `uuid`, `cuid`, `cuid2`, `ulid`, `nanoid`, `objectid`, `slug` | 各种 ID 格式 |
|
|
474
|
+
| **网络** | `url`, `uri`, `ipv4`, `ipv6`, `ip`, `cidr`, `hostname` | 网络地址 |
|
|
475
|
+
| **日期时间** | `date`, `time`, `date-time`, `datetime`, `duration` | ISO 8601 格式 |
|
|
476
|
+
| **手机号** | `phone` (中国), `phone-cn`, `phone-e164` (国际) | 电话号码 |
|
|
477
|
+
| **编码** | `base64`, `base64url`, `jwt` | 编码格式 |
|
|
478
|
+
| **颜色** | `hex-color`, `rgb-color`, `color` | 颜色值 |
|
|
479
|
+
| **其他** | `emoji`, `semver`, `credit-card` | 特殊格式 |
|
|
480
|
+
|
|
481
|
+
**自定义 Format:**
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
import { registerFormat, Patterns } from 'vafast';
|
|
485
|
+
|
|
486
|
+
// 注册自定义 format
|
|
487
|
+
registerFormat('order-id', (v) => /^ORD-\d{8}$/.test(v));
|
|
488
|
+
|
|
489
|
+
// 使用内置正则(供外部使用)
|
|
490
|
+
const isEmail = Patterns.EMAIL.test('test@example.com');
|
|
491
|
+
```
|
|
492
|
+
|
|
448
493
|
### 中间件预编译
|
|
449
494
|
|
|
450
495
|
Vafast 自动在路由注册时预编译中间件链,消除运行时组合开销:
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export { getLocals, setLocals } from './utils/handle.js';
|
|
|
12
12
|
export { createRequestValidator, parseAndValidateRequest, parseRequest, validateRequest } from './utils/request-validator.js';
|
|
13
13
|
export { HtmlRenderer } from './utils/html-renderer.js';
|
|
14
14
|
export { DependencyManager } from './utils/dependency-manager.js';
|
|
15
|
-
export { createValidator, getValidatorCacheStats, precompileSchemas, validateFast, validateSchema } from './utils/validators/validators.js';
|
|
15
|
+
export { SchemaConfig, ValidationError, ValidationResult, createValidator, getValidatorCacheStats, precompileSchemas, validateAllSchemas, validateFast, validateSchema, validateSchemaOrThrow } from './utils/validators/validators.js';
|
|
16
|
+
export { Patterns, hasFormat, registerFormat, registerFormats } from './utils/formats.js';
|
|
16
17
|
export { flattenNestedRoutes, normalizePath } from './router.js';
|
|
17
18
|
export { requireAuth } from './middleware/authMiddleware.js';
|
|
18
19
|
export { rateLimit } from './middleware/rateLimit.js';
|
|
@@ -25,6 +26,5 @@ export { BaseRouteConfig, CompatibleRoute, ExtendedRouteConfig, NestedRouteConfi
|
|
|
25
26
|
export { ComponentRoute, FlattenedComponentRoute, NestedComponentRoute } from './types/component-route.js';
|
|
26
27
|
export { HandlerContext, HandlerContextWithExtra, InferSchema, RouteSchema, TypedHandler, TypedRouteConfig } from './types/schema.js';
|
|
27
28
|
export { FetchHandler, ServeOptions, ServeResult, serve } from './node-server/serve.js';
|
|
28
|
-
export { Type } from '@sinclair/typebox';
|
|
29
|
-
import './utils/validators/schema-validators-ultra.js';
|
|
29
|
+
export { FormatRegistry, Type } from '@sinclair/typebox';
|
|
30
30
|
import 'node:http';
|
package/dist/index.js
CHANGED
|
@@ -1153,142 +1153,91 @@ function goAwait(promise) {
|
|
|
1153
1153
|
return promise.then((data) => [null, data]).catch((err) => [err instanceof Error ? err : new Error(String(err)), void 0]);
|
|
1154
1154
|
}
|
|
1155
1155
|
|
|
1156
|
-
// src/utils/validators/
|
|
1156
|
+
// src/utils/validators/validators.ts
|
|
1157
|
+
import { Type } from "@sinclair/typebox";
|
|
1157
1158
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
1158
|
-
var
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
// 2
|
|
1163
|
-
PARAMS: 1 << 2,
|
|
1164
|
-
// 4
|
|
1165
|
-
HEADERS: 1 << 3,
|
|
1166
|
-
// 8
|
|
1167
|
-
COOKIES: 1 << 4
|
|
1168
|
-
// 16
|
|
1169
|
-
};
|
|
1170
|
-
var ultraSchemaCache = /* @__PURE__ */ new Map();
|
|
1171
|
-
var schemaCacheHits = /* @__PURE__ */ new Map();
|
|
1172
|
-
var errorPool = [];
|
|
1173
|
-
var ERROR_POOL_SIZE = 200;
|
|
1174
|
-
var errorMessagePool = /* @__PURE__ */ new Map();
|
|
1175
|
-
var commonMessages = [
|
|
1176
|
-
"\u8BF7\u6C42\u4F53\u9A8C\u8BC1\u5931\u8D25",
|
|
1177
|
-
"Query\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25",
|
|
1178
|
-
"\u8DEF\u5F84\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25",
|
|
1179
|
-
"\u8BF7\u6C42\u5934\u9A8C\u8BC1\u5931\u8D25",
|
|
1180
|
-
"Cookie\u9A8C\u8BC1\u5931\u8D25",
|
|
1181
|
-
"\u7C7B\u578B\u9A8C\u8BC1\u5931\u8D25",
|
|
1182
|
-
"Schema\u7F16\u8BD1\u5931\u8D25",
|
|
1183
|
-
"\u672A\u77E5\u9519\u8BEF"
|
|
1184
|
-
];
|
|
1185
|
-
commonMessages.forEach((msg) => errorMessagePool.set(msg, msg));
|
|
1186
|
-
for (let i = 0; i < ERROR_POOL_SIZE; i++) {
|
|
1187
|
-
errorPool.push(new Error());
|
|
1188
|
-
}
|
|
1189
|
-
var errorPoolIndex = 0;
|
|
1190
|
-
function getErrorFromPool(message) {
|
|
1191
|
-
const error = errorPool[errorPoolIndex];
|
|
1192
|
-
error.message = message;
|
|
1193
|
-
errorPoolIndex = (errorPoolIndex + 1) % ERROR_POOL_SIZE;
|
|
1194
|
-
return error;
|
|
1195
|
-
}
|
|
1196
|
-
function getPooledString(key) {
|
|
1197
|
-
let pooled = errorMessagePool.get(key);
|
|
1198
|
-
if (!pooled) {
|
|
1199
|
-
pooled = key;
|
|
1200
|
-
errorMessagePool.set(key, key);
|
|
1201
|
-
}
|
|
1202
|
-
return pooled;
|
|
1203
|
-
}
|
|
1204
|
-
function getUltraSchemaCompiler(schema) {
|
|
1205
|
-
let compiler = ultraSchemaCache.get(schema);
|
|
1206
|
-
if (compiler) {
|
|
1207
|
-
schemaCacheHits.set(schema, (schemaCacheHits.get(schema) || 0) + 1);
|
|
1208
|
-
return compiler;
|
|
1209
|
-
}
|
|
1210
|
-
try {
|
|
1159
|
+
var compilerCache = /* @__PURE__ */ new WeakMap();
|
|
1160
|
+
function getCompiledValidator(schema) {
|
|
1161
|
+
let compiler = compilerCache.get(schema);
|
|
1162
|
+
if (!compiler) {
|
|
1211
1163
|
compiler = TypeCompiler.Compile(schema);
|
|
1212
|
-
|
|
1213
|
-
return compiler;
|
|
1214
|
-
} catch (error) {
|
|
1215
|
-
return null;
|
|
1164
|
+
compilerCache.set(schema, compiler);
|
|
1216
1165
|
}
|
|
1166
|
+
return compiler;
|
|
1217
1167
|
}
|
|
1218
|
-
function
|
|
1219
|
-
let flags = 0;
|
|
1220
|
-
if (config.body) flags |= SCHEMA_FLAGS.BODY;
|
|
1221
|
-
if (config.query) flags |= SCHEMA_FLAGS.QUERY;
|
|
1222
|
-
if (config.params) flags |= SCHEMA_FLAGS.PARAMS;
|
|
1223
|
-
if (config.headers) flags |= SCHEMA_FLAGS.HEADERS;
|
|
1224
|
-
if (config.cookies) flags |= SCHEMA_FLAGS.COOKIES;
|
|
1225
|
-
return flags;
|
|
1226
|
-
}
|
|
1227
|
-
function validateSchemaUltra(schema, data, context) {
|
|
1228
|
-
if (!schema) return data;
|
|
1168
|
+
function validateSchema(schema, data) {
|
|
1229
1169
|
try {
|
|
1230
|
-
|
|
1231
|
-
if (
|
|
1232
|
-
|
|
1233
|
-
compiler = TypeCompiler.Compile(schema);
|
|
1234
|
-
ultraSchemaCache.set(schema, compiler);
|
|
1235
|
-
} catch (error) {
|
|
1236
|
-
const message = getPooledString(`${context}\u9A8C\u8BC1\u5931\u8D25: Schema\u7F16\u8BD1\u5931\u8D25`);
|
|
1237
|
-
throw getErrorFromPool(message);
|
|
1238
|
-
}
|
|
1170
|
+
const compiler = getCompiledValidator(schema);
|
|
1171
|
+
if (compiler.Check(data)) {
|
|
1172
|
+
return { success: true, data };
|
|
1239
1173
|
}
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1174
|
+
const errors = [];
|
|
1175
|
+
for (const error of compiler.Errors(data)) {
|
|
1176
|
+
errors.push({
|
|
1177
|
+
path: error.path,
|
|
1178
|
+
message: error.message,
|
|
1179
|
+
code: "VALIDATION_FAILED",
|
|
1180
|
+
value: error.value
|
|
1181
|
+
});
|
|
1244
1182
|
}
|
|
1245
|
-
return
|
|
1183
|
+
return { success: false, errors };
|
|
1246
1184
|
} catch (error) {
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1185
|
+
return {
|
|
1186
|
+
success: false,
|
|
1187
|
+
errors: [
|
|
1188
|
+
{
|
|
1189
|
+
path: "",
|
|
1190
|
+
message: error instanceof Error ? error.message : "\u9A8C\u8BC1\u5F02\u5E38",
|
|
1191
|
+
code: "VALIDATION_EXCEPTION"
|
|
1192
|
+
}
|
|
1193
|
+
]
|
|
1194
|
+
};
|
|
1254
1195
|
}
|
|
1255
1196
|
}
|
|
1256
|
-
function
|
|
1257
|
-
const
|
|
1258
|
-
if (
|
|
1259
|
-
|
|
1260
|
-
}
|
|
1261
|
-
if (flags & SCHEMA_FLAGS.QUERY) {
|
|
1262
|
-
validateSchemaUltra(config.query, data.query, "Query\u53C2\u6570");
|
|
1263
|
-
}
|
|
1264
|
-
if (flags & SCHEMA_FLAGS.PARAMS) {
|
|
1265
|
-
validateSchemaUltra(config.params, data.params, "\u8DEF\u5F84\u53C2\u6570");
|
|
1266
|
-
}
|
|
1267
|
-
if (flags & SCHEMA_FLAGS.HEADERS) {
|
|
1268
|
-
validateSchemaUltra(config.headers, data.headers, "\u8BF7\u6C42\u5934");
|
|
1269
|
-
}
|
|
1270
|
-
if (flags & SCHEMA_FLAGS.COOKIES) {
|
|
1271
|
-
validateSchemaUltra(config.cookies, data.cookies, "Cookie");
|
|
1197
|
+
function validateSchemaOrThrow(schema, data, context) {
|
|
1198
|
+
const compiler = getCompiledValidator(schema);
|
|
1199
|
+
if (!compiler.Check(data)) {
|
|
1200
|
+
throw new Error(`${context}\u9A8C\u8BC1\u5931\u8D25`);
|
|
1272
1201
|
}
|
|
1273
1202
|
return data;
|
|
1274
1203
|
}
|
|
1275
|
-
function
|
|
1276
|
-
const
|
|
1277
|
-
|
|
1278
|
-
|
|
1204
|
+
function validateFast(schema, data) {
|
|
1205
|
+
const compiler = getCompiledValidator(schema);
|
|
1206
|
+
return compiler.Check(data);
|
|
1207
|
+
}
|
|
1208
|
+
function validateAllSchemas(config, data) {
|
|
1209
|
+
if (config.body) {
|
|
1210
|
+
validateSchemaOrThrow(config.body, data.body, "\u8BF7\u6C42\u4F53");
|
|
1279
1211
|
}
|
|
1280
|
-
if (
|
|
1281
|
-
|
|
1212
|
+
if (config.query) {
|
|
1213
|
+
validateSchemaOrThrow(config.query, data.query, "Query\u53C2\u6570");
|
|
1282
1214
|
}
|
|
1283
|
-
if (
|
|
1284
|
-
|
|
1215
|
+
if (config.params) {
|
|
1216
|
+
validateSchemaOrThrow(config.params, data.params, "\u8DEF\u5F84\u53C2\u6570");
|
|
1285
1217
|
}
|
|
1286
|
-
if (
|
|
1287
|
-
|
|
1218
|
+
if (config.headers) {
|
|
1219
|
+
validateSchemaOrThrow(config.headers, data.headers, "\u8BF7\u6C42\u5934");
|
|
1288
1220
|
}
|
|
1289
|
-
if (
|
|
1290
|
-
|
|
1221
|
+
if (config.cookies) {
|
|
1222
|
+
validateSchemaOrThrow(config.cookies, data.cookies, "Cookie");
|
|
1291
1223
|
}
|
|
1224
|
+
return data;
|
|
1225
|
+
}
|
|
1226
|
+
function precompileSchemas(config) {
|
|
1227
|
+
if (config.body) getCompiledValidator(config.body);
|
|
1228
|
+
if (config.query) getCompiledValidator(config.query);
|
|
1229
|
+
if (config.params) getCompiledValidator(config.params);
|
|
1230
|
+
if (config.headers) getCompiledValidator(config.headers);
|
|
1231
|
+
if (config.cookies) getCompiledValidator(config.cookies);
|
|
1232
|
+
}
|
|
1233
|
+
function createValidator(schema) {
|
|
1234
|
+
return (data) => validateSchema(schema, data);
|
|
1235
|
+
}
|
|
1236
|
+
function getValidatorCacheStats() {
|
|
1237
|
+
return {
|
|
1238
|
+
cacheType: "WeakMap",
|
|
1239
|
+
note: "WeakMap \u7F13\u5B58\u4F1A\u968F Schema \u5BF9\u8C61\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u5185\u5B58\u6CC4\u6F0F\u98CE\u9669"
|
|
1240
|
+
};
|
|
1292
1241
|
}
|
|
1293
1242
|
|
|
1294
1243
|
// src/utils/create-handler.ts
|
|
@@ -1363,7 +1312,7 @@ function createHandler(schemaOrHandler, maybeHandler) {
|
|
|
1363
1312
|
const schema = hasSchema ? schemaOrHandler : {};
|
|
1364
1313
|
const handler = hasSchema ? maybeHandler : schemaOrHandler;
|
|
1365
1314
|
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {
|
|
1366
|
-
|
|
1315
|
+
precompileSchemas(schema);
|
|
1367
1316
|
}
|
|
1368
1317
|
return async (req) => {
|
|
1369
1318
|
try {
|
|
@@ -1378,7 +1327,7 @@ function createHandler(schemaOrHandler, maybeHandler) {
|
|
|
1378
1327
|
}
|
|
1379
1328
|
const data = { body, query, params, headers, cookies };
|
|
1380
1329
|
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {
|
|
1381
|
-
|
|
1330
|
+
validateAllSchemas(schema, data);
|
|
1382
1331
|
}
|
|
1383
1332
|
const result = await handler({
|
|
1384
1333
|
req,
|
|
@@ -1402,7 +1351,7 @@ function createHandlerWithExtra(schemaOrHandler, maybeHandler) {
|
|
|
1402
1351
|
const schema = hasSchema ? schemaOrHandler : {};
|
|
1403
1352
|
const handler = hasSchema ? maybeHandler : schemaOrHandler;
|
|
1404
1353
|
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {
|
|
1405
|
-
|
|
1354
|
+
precompileSchemas(schema);
|
|
1406
1355
|
}
|
|
1407
1356
|
return async (req) => {
|
|
1408
1357
|
try {
|
|
@@ -1417,7 +1366,7 @@ function createHandlerWithExtra(schemaOrHandler, maybeHandler) {
|
|
|
1417
1366
|
}
|
|
1418
1367
|
const data = { body, query, params, headers, cookies };
|
|
1419
1368
|
if (schema.body || schema.query || schema.params || schema.headers || schema.cookies) {
|
|
1420
|
-
|
|
1369
|
+
validateAllSchemas(schema, data);
|
|
1421
1370
|
}
|
|
1422
1371
|
const extras = req.__locals ?? {};
|
|
1423
1372
|
const result = await handler({
|
|
@@ -1489,7 +1438,7 @@ async function parseRequest(request, params) {
|
|
|
1489
1438
|
}
|
|
1490
1439
|
function validateRequest(config, requestData) {
|
|
1491
1440
|
try {
|
|
1492
|
-
const validatedData =
|
|
1441
|
+
const validatedData = validateAllSchemas(config, requestData);
|
|
1493
1442
|
return {
|
|
1494
1443
|
success: true,
|
|
1495
1444
|
data: validatedData
|
|
@@ -1528,90 +1477,115 @@ function createRequestValidator(config) {
|
|
|
1528
1477
|
};
|
|
1529
1478
|
}
|
|
1530
1479
|
|
|
1531
|
-
// src/utils/
|
|
1532
|
-
import {
|
|
1533
|
-
|
|
1534
|
-
var
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1480
|
+
// src/utils/formats.ts
|
|
1481
|
+
import { FormatRegistry } from "@sinclair/typebox";
|
|
1482
|
+
var EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
1483
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
1484
|
+
var UUID_ANY_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1485
|
+
var CUID_REGEX = /^c[^\s-]{8,}$/i;
|
|
1486
|
+
var CUID2_REGEX = /^[0-9a-z]+$/;
|
|
1487
|
+
var ULID_REGEX = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
|
|
1488
|
+
var NANOID_REGEX = /^[A-Za-z0-9_-]{21}$/;
|
|
1489
|
+
var URL_REGEX = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$/;
|
|
1490
|
+
var IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
1491
|
+
var IPV6_REGEX = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$/;
|
|
1492
|
+
var CIDR_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(?:3[0-2]|[12]?[0-9])$/;
|
|
1493
|
+
var DATE_REGEX = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])$/;
|
|
1494
|
+
var TIME_REGEX = /^(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.\d{1,3})?$/;
|
|
1495
|
+
var DATE_TIME_REGEX = /^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.\d{1,3})?(?:Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])?$/;
|
|
1496
|
+
var DURATION_REGEX = /^P(?:\d+Y)?(?:\d+M)?(?:\d+W)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/;
|
|
1497
|
+
var HOSTNAME_REGEX = /^(?=.{1,253}$)(?:(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)*(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;
|
|
1498
|
+
var PHONE_CN_REGEX = /^1[3-9]\d{9}$/;
|
|
1499
|
+
var PHONE_E164_REGEX = /^\+[1-9]\d{6,14}$/;
|
|
1500
|
+
var OBJECTID_REGEX = /^[0-9a-fA-F]{24}$/;
|
|
1501
|
+
var HEX_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
|
|
1502
|
+
var RGB_COLOR_REGEX = /^rgba?\(\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s*,\s*(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/;
|
|
1503
|
+
var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
1504
|
+
var BASE64URL_REGEX = /^[A-Za-z0-9_-]+$/;
|
|
1505
|
+
var JWT_REGEX = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
1506
|
+
var EMOJI_REGEX = /^[\p{Emoji}]+$/u;
|
|
1507
|
+
var SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
1508
|
+
var SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
1509
|
+
function isValidCreditCard(value) {
|
|
1510
|
+
const digits = value.replace(/\D/g, "");
|
|
1511
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
1512
|
+
let sum = 0;
|
|
1513
|
+
let isEven = false;
|
|
1514
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
1515
|
+
let digit = parseInt(digits[i], 10);
|
|
1516
|
+
if (isEven) {
|
|
1517
|
+
digit *= 2;
|
|
1518
|
+
if (digit > 9) digit -= 9;
|
|
1519
|
+
}
|
|
1520
|
+
sum += digit;
|
|
1521
|
+
isEven = !isEven;
|
|
1522
|
+
}
|
|
1523
|
+
return sum % 10 === 0;
|
|
1524
|
+
}
|
|
1525
|
+
var isRegistered = false;
|
|
1526
|
+
function registerFormats() {
|
|
1527
|
+
if (isRegistered) return;
|
|
1528
|
+
isRegistered = true;
|
|
1529
|
+
FormatRegistry.Set("email", (v) => EMAIL_REGEX.test(v));
|
|
1530
|
+
FormatRegistry.Set("uuid", (v) => UUID_REGEX.test(v));
|
|
1531
|
+
FormatRegistry.Set("uuid-any", (v) => UUID_ANY_REGEX.test(v));
|
|
1532
|
+
FormatRegistry.Set("cuid", (v) => CUID_REGEX.test(v));
|
|
1533
|
+
FormatRegistry.Set("cuid2", (v) => CUID2_REGEX.test(v) && v.length >= 1);
|
|
1534
|
+
FormatRegistry.Set("ulid", (v) => ULID_REGEX.test(v));
|
|
1535
|
+
FormatRegistry.Set("nanoid", (v) => NANOID_REGEX.test(v));
|
|
1536
|
+
FormatRegistry.Set("objectid", (v) => OBJECTID_REGEX.test(v));
|
|
1537
|
+
FormatRegistry.Set("slug", (v) => SLUG_REGEX.test(v));
|
|
1538
|
+
FormatRegistry.Set("url", (v) => URL_REGEX.test(v));
|
|
1539
|
+
FormatRegistry.Set("uri", (v) => URL_REGEX.test(v));
|
|
1540
|
+
FormatRegistry.Set("ipv4", (v) => IPV4_REGEX.test(v));
|
|
1541
|
+
FormatRegistry.Set("ipv6", (v) => IPV6_REGEX.test(v));
|
|
1542
|
+
FormatRegistry.Set("ip", (v) => IPV4_REGEX.test(v) || IPV6_REGEX.test(v));
|
|
1543
|
+
FormatRegistry.Set("cidr", (v) => CIDR_REGEX.test(v));
|
|
1544
|
+
FormatRegistry.Set("hostname", (v) => HOSTNAME_REGEX.test(v));
|
|
1545
|
+
FormatRegistry.Set("date", (v) => DATE_REGEX.test(v));
|
|
1546
|
+
FormatRegistry.Set("time", (v) => TIME_REGEX.test(v));
|
|
1547
|
+
FormatRegistry.Set("date-time", (v) => DATE_TIME_REGEX.test(v));
|
|
1548
|
+
FormatRegistry.Set("datetime", (v) => DATE_TIME_REGEX.test(v));
|
|
1549
|
+
FormatRegistry.Set("duration", (v) => DURATION_REGEX.test(v));
|
|
1550
|
+
FormatRegistry.Set("phone", (v) => PHONE_CN_REGEX.test(v));
|
|
1551
|
+
FormatRegistry.Set("phone-cn", (v) => PHONE_CN_REGEX.test(v));
|
|
1552
|
+
FormatRegistry.Set("phone-e164", (v) => PHONE_E164_REGEX.test(v));
|
|
1553
|
+
FormatRegistry.Set("base64", (v) => BASE64_REGEX.test(v));
|
|
1554
|
+
FormatRegistry.Set("base64url", (v) => BASE64URL_REGEX.test(v));
|
|
1555
|
+
FormatRegistry.Set("jwt", (v) => JWT_REGEX.test(v));
|
|
1556
|
+
FormatRegistry.Set("hex-color", (v) => HEX_COLOR_REGEX.test(v));
|
|
1557
|
+
FormatRegistry.Set("rgb-color", (v) => RGB_COLOR_REGEX.test(v));
|
|
1558
|
+
FormatRegistry.Set(
|
|
1559
|
+
"color",
|
|
1560
|
+
(v) => HEX_COLOR_REGEX.test(v) || RGB_COLOR_REGEX.test(v)
|
|
1561
|
+
);
|
|
1562
|
+
FormatRegistry.Set("emoji", (v) => EMOJI_REGEX.test(v));
|
|
1563
|
+
FormatRegistry.Set("semver", (v) => SEMVER_REGEX.test(v));
|
|
1564
|
+
FormatRegistry.Set("credit-card", isValidCreditCard);
|
|
1565
|
+
}
|
|
1566
|
+
function registerFormat(name, validator) {
|
|
1567
|
+
FormatRegistry.Set(name, validator);
|
|
1568
|
+
}
|
|
1569
|
+
function hasFormat(name) {
|
|
1570
|
+
return FormatRegistry.Has(name);
|
|
1571
|
+
}
|
|
1572
|
+
var Patterns = {
|
|
1573
|
+
EMAIL: EMAIL_REGEX,
|
|
1574
|
+
UUID: UUID_REGEX,
|
|
1575
|
+
URL: URL_REGEX,
|
|
1576
|
+
IPV4: IPV4_REGEX,
|
|
1577
|
+
IPV6: IPV6_REGEX,
|
|
1578
|
+
DATE: DATE_REGEX,
|
|
1579
|
+
TIME: TIME_REGEX,
|
|
1580
|
+
DATE_TIME: DATE_TIME_REGEX,
|
|
1581
|
+
PHONE_CN: PHONE_CN_REGEX,
|
|
1582
|
+
PHONE_E164: PHONE_E164_REGEX,
|
|
1583
|
+
OBJECTID: OBJECTID_REGEX,
|
|
1584
|
+
HEX_COLOR: HEX_COLOR_REGEX,
|
|
1585
|
+
SLUG: SLUG_REGEX,
|
|
1586
|
+
SEMVER: SEMVER_REGEX,
|
|
1587
|
+
JWT: JWT_REGEX
|
|
1588
|
+
};
|
|
1615
1589
|
|
|
1616
1590
|
// src/middleware/authMiddleware.ts
|
|
1617
1591
|
var requireAuth = async (req, next) => {
|
|
@@ -2153,12 +2127,15 @@ function serve(options, callback) {
|
|
|
2153
2127
|
}
|
|
2154
2128
|
|
|
2155
2129
|
// src/index.ts
|
|
2156
|
-
import { Type as Type2 } from "@sinclair/typebox";
|
|
2130
|
+
import { Type as Type2, FormatRegistry as FormatRegistry2 } from "@sinclair/typebox";
|
|
2131
|
+
registerFormats();
|
|
2157
2132
|
export {
|
|
2158
2133
|
BaseServer,
|
|
2159
2134
|
ComponentServer,
|
|
2160
2135
|
DependencyManager,
|
|
2136
|
+
FormatRegistry2 as FormatRegistry,
|
|
2161
2137
|
HtmlRenderer,
|
|
2138
|
+
Patterns,
|
|
2162
2139
|
Server,
|
|
2163
2140
|
ServerFactory,
|
|
2164
2141
|
TokenError,
|
|
@@ -2188,6 +2165,7 @@ export {
|
|
|
2188
2165
|
getTokenTimeRemaining,
|
|
2189
2166
|
getValidatorCacheStats,
|
|
2190
2167
|
goAwait,
|
|
2168
|
+
hasFormat,
|
|
2191
2169
|
html,
|
|
2192
2170
|
isTokenExpired,
|
|
2193
2171
|
isTypedRoute,
|
|
@@ -2206,15 +2184,19 @@ export {
|
|
|
2206
2184
|
rateLimit,
|
|
2207
2185
|
redirect,
|
|
2208
2186
|
refreshToken,
|
|
2187
|
+
registerFormat,
|
|
2188
|
+
registerFormats,
|
|
2209
2189
|
requireAuth,
|
|
2210
2190
|
serve,
|
|
2211
2191
|
setLocals,
|
|
2212
2192
|
simpleHandler,
|
|
2213
2193
|
stream,
|
|
2214
2194
|
text,
|
|
2195
|
+
validateAllSchemas,
|
|
2215
2196
|
validateFast,
|
|
2216
2197
|
validateRequest,
|
|
2217
2198
|
validateSchema,
|
|
2199
|
+
validateSchemaOrThrow,
|
|
2218
2200
|
verifyToken
|
|
2219
2201
|
};
|
|
2220
2202
|
/**
|
|
@@ -2225,25 +2207,6 @@ export {
|
|
|
2225
2207
|
* @version 1.0.0
|
|
2226
2208
|
* @license MIT
|
|
2227
2209
|
*/
|
|
2228
|
-
/**
|
|
2229
|
-
* 超优化版Schema验证器 v5.0.0
|
|
2230
|
-
*
|
|
2231
|
-
* 使用经过验证的优化技术,确保极致性能
|
|
2232
|
-
* - 内联函数调用
|
|
2233
|
-
* - 预编译缓存优化
|
|
2234
|
-
* - 内存池优化
|
|
2235
|
-
* - 位运算优化
|
|
2236
|
-
* - 类型特化优化
|
|
2237
|
-
* - 循环展开优化
|
|
2238
|
-
* - 位掩码优化
|
|
2239
|
-
* - 字符串池优化
|
|
2240
|
-
* - 内联缓存优化
|
|
2241
|
-
* - 内存对齐优化
|
|
2242
|
-
*
|
|
2243
|
-
* @author Framework Team
|
|
2244
|
-
* @version 5.0.0
|
|
2245
|
-
* @license MIT
|
|
2246
|
-
*/
|
|
2247
2210
|
/**
|
|
2248
2211
|
* 类型安全的路由处理器工厂
|
|
2249
2212
|
*
|