feat(api): 搭建 API 与 Worker 骨架及契约基线
NestJS 11 + Fastify 统一错误体与 trace_id,/health 真实探活 DB/Redis,OpenAPI 3.1 契约含 20 个错误码;shared 包提供错误码、权限点、ULID、分页与通用 schema;worker 完成队列进程骨架。
This commit is contained in:
1 parent
09dbb27b66
commit
23067edb8f
70 files changed
+2445
No files matched your search
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 统一错误码(docs/工程规范/04-API与路由规范.md §4)
|
||||
* API-14:新增错误码必须集中登记在这里,禁止业务代码写裸数字。
|
||||
*/
|
||||
export const ErrorCode = {
|
||||
/** 400xx 参数校验 */
|
||||
PARAM_INVALID: 40001,
|
||||
|
||||
/** 401xx 认证 */
|
||||
UNAUTHENTICATED: 40101,
|
||||
TOKEN_EXPIRED: 40102,
|
||||
SIGNATURE_INVALID: 40103,
|
||||
|
||||
/** 403xx 授权 */
|
||||
PERMISSION_DENIED: 40301,
|
||||
OUT_OF_SCOPE: 40302,
|
||||
SPECIAL_PERMISSION_REQUIRED: 40303,
|
||||
SOD_VIOLATION: 40304,
|
||||
|
||||
/** 404xx 不存在 */
|
||||
NOT_FOUND: 40401,
|
||||
|
||||
/** 409xx 冲突 */
|
||||
VERSION_CONFLICT: 40901,
|
||||
DUPLICATE_SUBMIT: 40902,
|
||||
STATE_NOT_ALLOWED: 40903,
|
||||
|
||||
/** 422xx 业务规则 */
|
||||
BUSINESS_RULE_VIOLATION: 42201,
|
||||
COMPLIANCE_BLOCKED: 42202,
|
||||
COST_OVER_BUDGET: 42203,
|
||||
|
||||
/** 429xx 限流 */
|
||||
RATE_LIMITED: 42901,
|
||||
CONCURRENCY_LIMITED: 42902,
|
||||
|
||||
/** 500xx 系统 */
|
||||
INTERNAL_ERROR: 50001,
|
||||
DEPENDENCY_UNAVAILABLE: 50002,
|
||||
TIMEOUT: 50003,
|
||||
} as const;
|
||||
|
||||
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
||||
|
||||
/** 错误码 → HTTP 状态码(4xx/5xx 段由百位决定) */
|
||||
export const ERROR_HTTP_STATUS: Readonly<Record<ErrorCode, number>> = {
|
||||
[ErrorCode.PARAM_INVALID]: 400,
|
||||
[ErrorCode.UNAUTHENTICATED]: 401,
|
||||
[ErrorCode.TOKEN_EXPIRED]: 401,
|
||||
[ErrorCode.SIGNATURE_INVALID]: 401,
|
||||
[ErrorCode.PERMISSION_DENIED]: 403,
|
||||
[ErrorCode.OUT_OF_SCOPE]: 403,
|
||||
[ErrorCode.SPECIAL_PERMISSION_REQUIRED]: 403,
|
||||
[ErrorCode.SOD_VIOLATION]: 403,
|
||||
[ErrorCode.NOT_FOUND]: 404,
|
||||
[ErrorCode.VERSION_CONFLICT]: 409,
|
||||
[ErrorCode.DUPLICATE_SUBMIT]: 409,
|
||||
[ErrorCode.STATE_NOT_ALLOWED]: 409,
|
||||
[ErrorCode.BUSINESS_RULE_VIOLATION]: 422,
|
||||
[ErrorCode.COMPLIANCE_BLOCKED]: 422,
|
||||
[ErrorCode.COST_OVER_BUDGET]: 422,
|
||||
[ErrorCode.RATE_LIMITED]: 429,
|
||||
[ErrorCode.CONCURRENCY_LIMITED]: 429,
|
||||
[ErrorCode.INTERNAL_ERROR]: 500,
|
||||
[ErrorCode.DEPENDENCY_UNAVAILABLE]: 503,
|
||||
[ErrorCode.TIMEOUT]: 504,
|
||||
};
|
||||
|
||||
/** 默认中文提示(前端兜底展示;服务端可按场景覆盖 message) */
|
||||
export const ERROR_MESSAGES: Readonly<Record<ErrorCode, string>> = {
|
||||
[ErrorCode.PARAM_INVALID]: '参数缺失或格式错误',
|
||||
[ErrorCode.UNAUTHENTICATED]: '请先登录',
|
||||
[ErrorCode.TOKEN_EXPIRED]: '登录已过期,请重新登录',
|
||||
[ErrorCode.SIGNATURE_INVALID]: '签名校验失败',
|
||||
[ErrorCode.PERMISSION_DENIED]: '没有操作权限',
|
||||
[ErrorCode.OUT_OF_SCOPE]: '数据范围之外',
|
||||
[ErrorCode.SPECIAL_PERMISSION_REQUIRED]: '缺少特殊权限',
|
||||
[ErrorCode.SOD_VIOLATION]: '违反职责互斥,不能执行该操作',
|
||||
[ErrorCode.NOT_FOUND]: '资源不存在或已删除',
|
||||
[ErrorCode.VERSION_CONFLICT]: '数据已被他人修改,请刷新后重试',
|
||||
[ErrorCode.DUPLICATE_SUBMIT]: '请勿重复提交',
|
||||
[ErrorCode.STATE_NOT_ALLOWED]: '当前状态不允许该操作',
|
||||
[ErrorCode.BUSINESS_RULE_VIOLATION]: '业务校验未通过',
|
||||
[ErrorCode.COMPLIANCE_BLOCKED]: '内容触发合规拦截',
|
||||
[ErrorCode.COST_OVER_BUDGET]: '成本超出预算',
|
||||
[ErrorCode.RATE_LIMITED]: '请求过于频繁,请稍后再试',
|
||||
[ErrorCode.CONCURRENCY_LIMITED]: '并发任务已达上限',
|
||||
[ErrorCode.INTERNAL_ERROR]: '服务内部错误',
|
||||
[ErrorCode.DEPENDENCY_UNAVAILABLE]: '依赖服务不可用',
|
||||
[ErrorCode.TIMEOUT]: '请求超时',
|
||||
};
|
||||
|
||||
const ERROR_CODE_VALUES: ReadonlySet<number> = new Set(Object.values(ErrorCode));
|
||||
|
||||
export function isErrorCode(value: number): value is ErrorCode {
|
||||
return ERROR_CODE_VALUES.has(value);
|
||||
}
|
||||
|
||||
/** 数字错误码对应的 HTTP 状态;优先查表(502/503/504 等细分),非法码回退 500 */
|
||||
export function httpStatusOf(code: number): number {
|
||||
if (isErrorCode(code)) {
|
||||
return ERROR_HTTP_STATUS[code];
|
||||
}
|
||||
const segment = Math.floor(code / 100);
|
||||
return segment >= 400 && segment <= 599 ? segment : 500;
|
||||
}
|
||||
Reference in new issue
Block a user