@winspan/claude-forge 1.19.0 → 1.21.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/README.md +10 -10
- package/dist/pipeline/store.d.ts +12 -0
- package/dist/pipeline/store.d.ts.map +1 -1
- package/dist/pipeline/store.js +29 -5
- package/dist/pipeline/store.js.map +1 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +6 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/web/routes/claudemd.d.ts.map +1 -1
- package/dist/web/routes/claudemd.js +16 -13
- package/dist/web/routes/claudemd.js.map +1 -1
- package/dist/web/routes/config.d.ts.map +1 -1
- package/dist/web/routes/config.js +15 -13
- package/dist/web/routes/config.js.map +1 -1
- package/dist/web/routes/convention.d.ts.map +1 -1
- package/dist/web/routes/convention.js +12 -10
- package/dist/web/routes/convention.js.map +1 -1
- package/dist/web/routes/events.d.ts.map +1 -1
- package/dist/web/routes/events.js +21 -9
- package/dist/web/routes/events.js.map +1 -1
- package/dist/web/routes/knowledge.d.ts.map +1 -1
- package/dist/web/routes/knowledge.js +14 -10
- package/dist/web/routes/knowledge.js.map +1 -1
- package/dist/web/routes/memory.d.ts +7 -0
- package/dist/web/routes/memory.d.ts.map +1 -0
- package/dist/web/routes/memory.js +94 -0
- package/dist/web/routes/memory.js.map +1 -0
- package/dist/web/routes/pipelines.d.ts.map +1 -1
- package/dist/web/routes/pipelines.js +13 -13
- package/dist/web/routes/pipelines.js.map +1 -1
- package/dist/web/routes/projects.d.ts.map +1 -1
- package/dist/web/routes/projects.js +11 -18
- package/dist/web/routes/projects.js.map +1 -1
- package/dist/web/routes/quality.d.ts.map +1 -1
- package/dist/web/routes/quality.js +13 -9
- package/dist/web/routes/quality.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +7 -7
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +2 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web/utils/errors.d.ts +31 -0
- package/dist/web/utils/errors.d.ts.map +1 -0
- package/dist/web/utils/errors.js +56 -0
- package/dist/web/utils/errors.js.map +1 -0
- package/dist/web/utils/path-validation.d.ts +20 -0
- package/dist/web/utils/path-validation.d.ts.map +1 -0
- package/dist/web/utils/path-validation.js +55 -0
- package/dist/web/utils/path-validation.js.map +1 -0
- package/dist/web/utils/validation.d.ts +59 -0
- package/dist/web/utils/validation.d.ts.map +1 -0
- package/dist/web/utils/validation.js +101 -0
- package/dist/web/utils/validation.js.map +1 -0
- package/dist/web-static/assets/{index-CzccBOr0.js → index-CJwbFBHu.js} +1 -1
- package/dist/web-static/index.html +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* 统一的错误处理工具
|
|
4
|
+
* 避免敏感信息泄露,提供一致的错误响应格式
|
|
5
|
+
*/
|
|
6
|
+
/** 应用层错误基类 */
|
|
7
|
+
export class AppError extends Error {
|
|
8
|
+
statusCode;
|
|
9
|
+
isOperational;
|
|
10
|
+
constructor(message, statusCode = 500, isOperational = true) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.statusCode = statusCode;
|
|
13
|
+
this.isOperational = isOperational;
|
|
14
|
+
this.name = 'AppError';
|
|
15
|
+
Object.setPrototypeOf(this, AppError.prototype);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** 输入验证错误(400) */
|
|
19
|
+
export class ValidationError extends AppError {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message, 400);
|
|
22
|
+
this.name = 'ValidationError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** 资源未找到错误(404) */
|
|
26
|
+
export class NotFoundError extends AppError {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message, 404);
|
|
29
|
+
this.name = 'NotFoundError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** 路径安全错误(403) */
|
|
33
|
+
export class PathSecurityError extends AppError {
|
|
34
|
+
constructor(message) {
|
|
35
|
+
super(message, 403);
|
|
36
|
+
this.name = 'PathSecurityError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 统一的错误处理函数
|
|
41
|
+
* @param err 捕获的错误
|
|
42
|
+
* @param res Express 响应对象
|
|
43
|
+
* @param context 错误上下文(用于日志)
|
|
44
|
+
*/
|
|
45
|
+
export function handleError(err, res, context = 'unknown') {
|
|
46
|
+
// 记录详细错误到日志(内部可见)
|
|
47
|
+
logger.error(`[${context}] 错误:${err instanceof Error ? err.stack : String(err)}`);
|
|
48
|
+
if (err instanceof AppError) {
|
|
49
|
+
// 应用层错误:返回用户友好的消息
|
|
50
|
+
res.status(err.statusCode).json({ error: err.message });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// 未知错误:不暴露详细信息
|
|
54
|
+
res.status(500).json({ error: '服务器内部错误,请稍后重试' });
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/web/utils/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C;;;GAGG;AAEH,cAAc;AACd,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,aAAqB,GAAG,EACxB,gBAAyB,IAAI;QAE7C,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,eAAU,GAAV,UAAU,CAAc;QACxB,kBAAa,GAAb,aAAa,CAAgB;QAG7C,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;CACF;AAED,kBAAkB;AAClB,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,mBAAmB;AACnB,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,kBAAkB;AAClB,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,GAAY,EAAE,GAAa,EAAE,OAAO,GAAG,SAAS;IAC1E,kBAAkB;IAClB,MAAM,CAAC,KAAK,CAAC,IAAI,OAAO,QAAQ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAElF,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,kBAAkB;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,eAAe;IACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一的路径验证工具
|
|
3
|
+
* 用于防止路径遍历攻击
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 验证项目路径
|
|
7
|
+
* @param encodedPath URL 编码的路径
|
|
8
|
+
* @returns 验证后的绝对路径
|
|
9
|
+
* @throws Error 如果路径不合法
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateProjectPath(encodedPath: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* 验证文件路径(在项目路径下)
|
|
14
|
+
* @param projectPath 已验证的项目路径
|
|
15
|
+
* @param relativePath 相对路径
|
|
16
|
+
* @returns 验证后的绝对路径
|
|
17
|
+
* @throws Error 如果路径不合法
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateFilePath(projectPath: string, relativePath: string): string;
|
|
20
|
+
//# sourceMappingURL=path-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-validation.d.ts","sourceRoot":"","sources":["../../../src/web/utils/path-validation.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAwB/D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAkBlF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
/**
|
|
4
|
+
* 统一的路径验证工具
|
|
5
|
+
* 用于防止路径遍历攻击
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 验证项目路径
|
|
9
|
+
* @param encodedPath URL 编码的路径
|
|
10
|
+
* @returns 验证后的绝对路径
|
|
11
|
+
* @throws Error 如果路径不合法
|
|
12
|
+
*/
|
|
13
|
+
export function validateProjectPath(encodedPath) {
|
|
14
|
+
const projectPath = decodeURIComponent(encodedPath);
|
|
15
|
+
// 必须是绝对路径
|
|
16
|
+
if (!path.isAbsolute(projectPath)) {
|
|
17
|
+
throw new Error('项目路径必须是绝对路径');
|
|
18
|
+
}
|
|
19
|
+
// 规范化路径,防止 ../ 遍历
|
|
20
|
+
const normalized = path.normalize(projectPath);
|
|
21
|
+
const resolved = path.resolve(projectPath);
|
|
22
|
+
// 检查是否包含路径遍历
|
|
23
|
+
if (normalized !== projectPath || resolved !== normalized) {
|
|
24
|
+
throw new Error('路径包含非法字符');
|
|
25
|
+
}
|
|
26
|
+
// 可选:限制在用户主目录下(个人自用场景的安全边界)
|
|
27
|
+
const homeDir = os.homedir();
|
|
28
|
+
if (!resolved.startsWith(homeDir)) {
|
|
29
|
+
throw new Error('路径必须在用户主目录下');
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 验证文件路径(在项目路径下)
|
|
35
|
+
* @param projectPath 已验证的项目路径
|
|
36
|
+
* @param relativePath 相对路径
|
|
37
|
+
* @returns 验证后的绝对路径
|
|
38
|
+
* @throws Error 如果路径不合法
|
|
39
|
+
*/
|
|
40
|
+
export function validateFilePath(projectPath, relativePath) {
|
|
41
|
+
// 规范化相对路径
|
|
42
|
+
const normalized = path.normalize(relativePath);
|
|
43
|
+
// 不允许包含 ../
|
|
44
|
+
if (normalized.includes('..')) {
|
|
45
|
+
throw new Error('文件路径不能包含 ../');
|
|
46
|
+
}
|
|
47
|
+
// 拼接完整路径
|
|
48
|
+
const fullPath = path.join(projectPath, normalized);
|
|
49
|
+
// 确保在项目路径下
|
|
50
|
+
if (!fullPath.startsWith(projectPath)) {
|
|
51
|
+
throw new Error('文件路径必须在项目目录下');
|
|
52
|
+
}
|
|
53
|
+
return fullPath;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=path-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../../../src/web/utils/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB;;;GAGG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,MAAM,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAEpD,UAAU;IACV,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IAClB,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE3C,aAAa;IACb,IAAI,UAAU,KAAK,WAAW,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,4BAA4B;IAC5B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB,EAAE,YAAoB;IACxE,UAAU;IACV,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAEhD,YAAY;IACZ,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,SAAS;IACT,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAEpD,WAAW;IACX,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一的输入验证工具
|
|
3
|
+
* 用于验证 API 请求参数,防止注入攻击和数据异常
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 验证 limit 参数
|
|
7
|
+
* @param value 用户输入的值
|
|
8
|
+
* @param min 最小值(默认 1)
|
|
9
|
+
* @param max 最大值(默认 1000)
|
|
10
|
+
* @param defaultValue 默认值(默认 100)
|
|
11
|
+
* @returns 验证后的数值
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateLimit(value: unknown, min?: number, max?: number, defaultValue?: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* 验证正整数
|
|
16
|
+
* @param value 用户输入的值
|
|
17
|
+
* @param fieldName 字段名(用于错误提示)
|
|
18
|
+
* @returns 验证后的数值
|
|
19
|
+
* @throws Error 如果不是正整数
|
|
20
|
+
*/
|
|
21
|
+
export declare function validatePositiveInt(value: unknown, fieldName: string): number;
|
|
22
|
+
/**
|
|
23
|
+
* 验证非负整数
|
|
24
|
+
* @param value 用户输入的值
|
|
25
|
+
* @param fieldName 字段名(用于错误提示)
|
|
26
|
+
* @returns 验证后的数值
|
|
27
|
+
* @throws Error 如果不是非负整数
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateNonNegativeInt(value: unknown, fieldName: string): number;
|
|
30
|
+
/**
|
|
31
|
+
* 验证字符串长度
|
|
32
|
+
* @param value 用户输入的值
|
|
33
|
+
* @param fieldName 字段名(用于错误提示)
|
|
34
|
+
* @param minLength 最小长度(默认 1)
|
|
35
|
+
* @param maxLength 最大长度(默认 1000)
|
|
36
|
+
* @returns 验证后的字符串
|
|
37
|
+
* @throws Error 如果长度不符合要求
|
|
38
|
+
*/
|
|
39
|
+
export declare function validateStringLength(value: unknown, fieldName: string, minLength?: number, maxLength?: number): string;
|
|
40
|
+
/**
|
|
41
|
+
* 验证枚举值
|
|
42
|
+
* @param value 用户输入的值
|
|
43
|
+
* @param fieldName 字段名(用于错误提示)
|
|
44
|
+
* @param allowedValues 允许的值列表
|
|
45
|
+
* @returns 验证后的值
|
|
46
|
+
* @throws Error 如果不在允许的值列表中
|
|
47
|
+
*/
|
|
48
|
+
export declare function validateEnum<T extends string>(value: unknown, fieldName: string, allowedValues: readonly T[]): T;
|
|
49
|
+
/**
|
|
50
|
+
* 验证数组
|
|
51
|
+
* @param value 用户输入的值
|
|
52
|
+
* @param fieldName 字段名(用于错误提示)
|
|
53
|
+
* @param maxLength 最大长度(默认 100)
|
|
54
|
+
* @param minLength 最小长度(默认 0)
|
|
55
|
+
* @returns 验证后的数组
|
|
56
|
+
* @throws Error 如果不是数组或长度超限
|
|
57
|
+
*/
|
|
58
|
+
export declare function validateArray<T>(value: unknown, fieldName: string, maxLength?: number, minLength?: number): T[];
|
|
59
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/web/utils/validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,GAAG,SAAI,EACP,GAAG,SAAO,EACV,YAAY,SAAM,GACjB,MAAM,CAMR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM7E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,SAAI,EACb,SAAS,SAAO,GACf,MAAM,CAQR;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,SAAS,CAAC,EAAE,GAC1B,CAAC,CAKH;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,SAAM,EACf,SAAS,SAAI,GACZ,CAAC,EAAE,CAWL"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一的输入验证工具
|
|
3
|
+
* 用于验证 API 请求参数,防止注入攻击和数据异常
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 验证 limit 参数
|
|
7
|
+
* @param value 用户输入的值
|
|
8
|
+
* @param min 最小值(默认 1)
|
|
9
|
+
* @param max 最大值(默认 1000)
|
|
10
|
+
* @param defaultValue 默认值(默认 100)
|
|
11
|
+
* @returns 验证后的数值
|
|
12
|
+
*/
|
|
13
|
+
export function validateLimit(value, min = 1, max = 1000, defaultValue = 100) {
|
|
14
|
+
const num = Number(value);
|
|
15
|
+
if (!Number.isFinite(num) || num < min || num > max) {
|
|
16
|
+
return defaultValue;
|
|
17
|
+
}
|
|
18
|
+
return Math.floor(num);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 验证正整数
|
|
22
|
+
* @param value 用户输入的值
|
|
23
|
+
* @param fieldName 字段名(用于错误提示)
|
|
24
|
+
* @returns 验证后的数值
|
|
25
|
+
* @throws Error 如果不是正整数
|
|
26
|
+
*/
|
|
27
|
+
export function validatePositiveInt(value, fieldName) {
|
|
28
|
+
const num = Number(value);
|
|
29
|
+
if (!Number.isInteger(num) || num <= 0) {
|
|
30
|
+
throw new Error(`${fieldName} 必须是正整数`);
|
|
31
|
+
}
|
|
32
|
+
return num;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 验证非负整数
|
|
36
|
+
* @param value 用户输入的值
|
|
37
|
+
* @param fieldName 字段名(用于错误提示)
|
|
38
|
+
* @returns 验证后的数值
|
|
39
|
+
* @throws Error 如果不是非负整数
|
|
40
|
+
*/
|
|
41
|
+
export function validateNonNegativeInt(value, fieldName) {
|
|
42
|
+
const num = Number(value);
|
|
43
|
+
if (!Number.isInteger(num) || num < 0) {
|
|
44
|
+
throw new Error(`${fieldName} 必须是非负整数`);
|
|
45
|
+
}
|
|
46
|
+
return num;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 验证字符串长度
|
|
50
|
+
* @param value 用户输入的值
|
|
51
|
+
* @param fieldName 字段名(用于错误提示)
|
|
52
|
+
* @param minLength 最小长度(默认 1)
|
|
53
|
+
* @param maxLength 最大长度(默认 1000)
|
|
54
|
+
* @returns 验证后的字符串
|
|
55
|
+
* @throws Error 如果长度不符合要求
|
|
56
|
+
*/
|
|
57
|
+
export function validateStringLength(value, fieldName, minLength = 1, maxLength = 1000) {
|
|
58
|
+
if (typeof value !== 'string') {
|
|
59
|
+
throw new Error(`${fieldName} 必须是字符串`);
|
|
60
|
+
}
|
|
61
|
+
if (value.length < minLength || value.length > maxLength) {
|
|
62
|
+
throw new Error(`${fieldName} 长度必须在 ${minLength}-${maxLength} 之间`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 验证枚举值
|
|
68
|
+
* @param value 用户输入的值
|
|
69
|
+
* @param fieldName 字段名(用于错误提示)
|
|
70
|
+
* @param allowedValues 允许的值列表
|
|
71
|
+
* @returns 验证后的值
|
|
72
|
+
* @throws Error 如果不在允许的值列表中
|
|
73
|
+
*/
|
|
74
|
+
export function validateEnum(value, fieldName, allowedValues) {
|
|
75
|
+
if (typeof value !== 'string' || !allowedValues.includes(value)) {
|
|
76
|
+
throw new Error(`${fieldName} 必须是以下值之一: ${allowedValues.join(', ')}`);
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 验证数组
|
|
82
|
+
* @param value 用户输入的值
|
|
83
|
+
* @param fieldName 字段名(用于错误提示)
|
|
84
|
+
* @param maxLength 最大长度(默认 100)
|
|
85
|
+
* @param minLength 最小长度(默认 0)
|
|
86
|
+
* @returns 验证后的数组
|
|
87
|
+
* @throws Error 如果不是数组或长度超限
|
|
88
|
+
*/
|
|
89
|
+
export function validateArray(value, fieldName, maxLength = 100, minLength = 0) {
|
|
90
|
+
if (!Array.isArray(value)) {
|
|
91
|
+
throw new Error(`${fieldName} 必须是数组`);
|
|
92
|
+
}
|
|
93
|
+
if (value.length < minLength) {
|
|
94
|
+
throw new Error(`${fieldName} 长度不能少于 ${minLength}`);
|
|
95
|
+
}
|
|
96
|
+
if (value.length > maxLength) {
|
|
97
|
+
throw new Error(`${fieldName} 长度不能超过 ${maxLength}`);
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/web/utils/validation.ts"],"names":[],"mappings":"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"}
|