wildpig 2.2.6 → 2.3.0

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/decorators.ts ADDED
@@ -0,0 +1,5 @@
1
+
2
+
3
+
4
+
5
+ export { WildpigParamsGuard } from "./src/decorators/WildpigParamsGuard"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wildpig",
3
- "version": "2.2.6",
3
+ "version": "2.3.0",
4
4
  "author": "eriktse",
5
5
  "type": "module",
6
6
  "peerDependencies": {
@@ -0,0 +1,101 @@
1
+ import { getBodyFromRequest, getQueryObjectFromRequest } from "../utils/server/request";
2
+
3
+ interface IFieldValidate {
4
+ /** 是否必填 */
5
+ required: boolean;
6
+ /** 字段类型 */
7
+ type?: "string" | "number" | "boolean" | "array";
8
+ /** 最大长度,仅对string和array类型生效 */
9
+ maxLength?: number;
10
+ /** 最小长度,仅对string和array类型生效 */
11
+ minLength?: number;
12
+ /** 最大值,仅对number类型生效 */
13
+ maxValue?: number;
14
+ /** 最小值,仅对number类型生效 */
15
+ minValue?: number;
16
+ /** 自定义校验函数,返回true表示校验通过 */
17
+ custom?: (value: any) => boolean | Promise<boolean>;
18
+ }
19
+
20
+ interface IParamsGuardOption {
21
+ /** 校验params参数 */
22
+ query?: Omit<Record<string, IFieldValidate>, "type" | "maxValue" | "minValue">;
23
+ /** 校验body参数 */
24
+ body?: Record<string, IFieldValidate>;
25
+ /** 严格模式,开启后无定义的参数将被拒绝,default: true */
26
+ strict?: boolean;
27
+ }
28
+
29
+
30
+ export const WildpigParamsGuard = (options: IParamsGuardOption) =>(target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
31
+ const originalMethod = descriptor.value;
32
+ descriptor.value = async function (req: Request, payload: any) {
33
+ if(!payload)payload = {};
34
+ if(options.strict === undefined)options.strict = true;
35
+ // 获取query参数
36
+ const query = getQueryObjectFromRequest(req);
37
+ payload.query = query;
38
+ // 获取body参数
39
+ const body = await getBodyFromRequest(req);
40
+ payload.body = body;
41
+
42
+ // 如果严格模式开启,拒绝无定义的参数
43
+ if(options.strict){
44
+ const queryKeys = Object.keys(query);
45
+ const bodyKeys = Object.keys(body);
46
+ if(options.query){
47
+ for(const key of queryKeys)
48
+ if(!(key in options.query))return new Response(`不接受的query参数:${key}`, { status: 400 });
49
+ }
50
+ if(options.body){
51
+ for(const key of bodyKeys)
52
+ if(!(key in options.body))return new Response(`不接受的body参数:${key}`, { status: 400 });
53
+ }
54
+ }
55
+
56
+ // 校验query参数
57
+ if(options.query){
58
+ for(const key of Object.keys(options.query)){
59
+ const validate = options.query[key];
60
+ if(!validate)continue;
61
+
62
+ if(validate.required && !(key in query))return new Response(`query参数${key}必填`, { status: 400 });
63
+ if(validate.maxLength && query[key].length > validate.maxLength)return new Response(`query参数${key}长度超过设定值:${validate.maxLength}`, { status: 400 });
64
+ if(validate.minLength && query[key].length < validate.minLength)return new Response(`query参数${key}长度不足设定值:${validate.minLength}`, { status: 400 });
65
+ if(validate.custom && !(await validate.custom(query[key])))return new Response(`query参数${key}自定义校验失败`, { status: 400 });
66
+ }
67
+ }
68
+
69
+ // 校验body参数
70
+ if(options.body){
71
+ for(const key of Object.keys(options.body)){
72
+ const validate = options.body[key];
73
+ if(!validate)continue;
74
+
75
+ if(validate.required && !(key in body))return new Response(`body参数${key}必填`, { status: 400 });
76
+ if(!validate.type)continue;
77
+
78
+ if(["string", "number", "boolean"].includes(validate.type)){
79
+ if(typeof body[key] !== validate.type)return new Response(`body参数${key}类型错误`, { status: 400 });
80
+ }else if(validate.type === "array"){
81
+ if(!Array.isArray(body[key]))return new Response(`body参数${key}类型错误`, { status: 400 });
82
+ }
83
+
84
+ if(["string", "array"].includes(validate.type)){
85
+ if(validate.maxLength && body[key].length > validate.maxLength)return new Response(`body参数${key}长度超过设定值:${validate.maxLength}`, { status: 400 });
86
+ if(validate.minLength && body[key].length < validate.minLength)return new Response(`body参数${key}长度不足设定值:${validate.minLength}`, { status: 400 });
87
+ }
88
+
89
+ if(validate.type === "number"){
90
+ if(validate.maxValue && body[key] > validate.maxValue)return new Response(`body参数${key}超过最大值:${validate.maxValue}`, { status: 400 });
91
+ if(validate.minValue && body[key] < validate.minValue)return new Response(`body参数${key}低于最小值:${validate.minValue}`, { status: 400 });
92
+ }
93
+ if(validate.custom && !(await validate.custom(body[key])))return new Response(`body参数${key}自定义校验失败`, { status: 400 });
94
+
95
+ }
96
+ }
97
+
98
+ return originalMethod.apply(this, [req, payload]);
99
+ }
100
+ return descriptor as any;
101
+ }
@@ -0,0 +1,28 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+ export const getQueryObjectFromRequest = (req: Request) => {
11
+ const params = new URLSearchParams(req.url.split("?")[1]);
12
+ const queryObject: { [key: string]: string } = {};
13
+ params.forEach((value, key) => {
14
+ queryObject[key] = value;
15
+ });
16
+ return queryObject;
17
+ }
18
+
19
+ export const getBodyFromRequest = async (req: Request) => {
20
+ if(req.method === "GET")return {};
21
+
22
+ try{
23
+ const body = await req.json();
24
+ return body;
25
+ }catch(e){
26
+ throw "请求体格式错误";
27
+ }
28
+ }