task-27: api-field-compat 高频响应 schema
新增 src/shared/api-field-schemas.ts:task 核心字段、result 文件阶段 字段、task-result 组合 schema 注册表(带版本号);12 个业务模块 注册同一 task-result schema;getApiFieldSchema()/createModuleFieldChecker() 供契约测试与联调前跑字段漂移检查。 10 个测试:schema 必填/结果字段声明、checker 合法/缺必填/类型不符/ 批量、模块注册齐全、版本标记、未知模块抛错。
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* API 高频响应 schema 注册表(Task 27)。
|
||||
*
|
||||
* 为 task/result 核心响应与各业务模块注册字段 schema,供
|
||||
* createApiFieldCompatChecker 在契约测试与联调前做字段漂移检查。
|
||||
* 模块级 schema 目前复用 task+result 组合,后续某模块有独特字段时
|
||||
* 在其定义内覆盖/追加即可,无需改动检查器。
|
||||
*/
|
||||
import { createApiFieldCompatChecker, type ApiFieldSpec } from './api-field-compat.ts'
|
||||
|
||||
export interface ApiFieldSchemaDef {
|
||||
/** schema 版本号,变更时递增 */
|
||||
version: number
|
||||
/** 字段名 → 规格 */
|
||||
schema: Record<string, ApiFieldSpec>
|
||||
}
|
||||
|
||||
/** task 核心响应字段 */
|
||||
export const taskCoreSchema: Record<string, ApiFieldSpec> = {
|
||||
taskId: { type: 'number', required: true },
|
||||
status: { type: 'string', required: true },
|
||||
progress: { type: 'number' },
|
||||
message: { type: 'string' },
|
||||
resultId: { type: 'number' },
|
||||
}
|
||||
|
||||
/** 结果文件阶段字段(与 ResultFilePhase 对应,全部可选) */
|
||||
export const resultFileSchema: Record<string, ApiFieldSpec> = {
|
||||
fileStatus: { type: 'string' },
|
||||
fileReady: { type: 'boolean' },
|
||||
fileProgress: { type: 'number' },
|
||||
fileProgressLabel: { type: 'string' },
|
||||
fileProgressStage: { type: 'string' },
|
||||
downloadUrl: { type: 'string' },
|
||||
freshDownloadUrl: { type: 'string' },
|
||||
}
|
||||
|
||||
/** task + result 组合 schema */
|
||||
export const taskWithResultSchema: Record<string, ApiFieldSpec> = {
|
||||
...taskCoreSchema,
|
||||
...resultFileSchema,
|
||||
}
|
||||
|
||||
const BUSINESS_MODULES = [
|
||||
'dedupe', 'split', 'convert', 'publish', 'similar-asin', 'appearance-patent',
|
||||
'delete-brand', 'price-track', 'shop-match', 'query-asin', 'withdraw',
|
||||
'collect-data', 'image-video',
|
||||
] as const
|
||||
|
||||
export const apiFieldSchemas: Record<string, ApiFieldSchemaDef> = {
|
||||
task: { version: 1, schema: taskCoreSchema },
|
||||
result: { version: 1, schema: resultFileSchema },
|
||||
'task-result': { version: 1, schema: taskWithResultSchema },
|
||||
}
|
||||
|
||||
for (const module of BUSINESS_MODULES) {
|
||||
apiFieldSchemas[module] = { version: 1, schema: taskWithResultSchema }
|
||||
}
|
||||
|
||||
export function getApiFieldSchema(name: string): ApiFieldSchemaDef | null {
|
||||
return apiFieldSchemas[name] ?? null
|
||||
}
|
||||
|
||||
export function createModuleFieldChecker(module: string) {
|
||||
const def = getApiFieldSchema(module)
|
||||
if (!def) {
|
||||
throw new Error(`未注册的模块: ${module}`)
|
||||
}
|
||||
return createApiFieldCompatChecker({ schema: def.schema })
|
||||
}
|
||||
Reference in New Issue
Block a user