Files
NextEdu/src/modules/files/schema.ts
SpecialX e9a5264fe7 feat(parent,auth,onboarding,files,notifications,adaptive-practice,ai): add module updates
parent:

- Add parent-student-attendance-detail component

auth:

- Add actions, data-access, schema, services, types

onboarding:

- Add parent-children-form and hooks directory

files:

- Add actions, schema, hooks directory

notifications:

- Add schema and schema test

adaptive-practice:

- Add answer-input, answer-result, practice-result-view, practice-starter-with-nav

- Add question-card, question-content, lib and services directories

ai:

- Add context/create-ai-client-service, hooks/use-drag-position, hooks/use-position-persistence
2026-07-03 10:26:12 +08:00

85 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { z } from "zod"
import { MAX_FILE_SIZE } from "@/shared/lib/file-storage"
import type { FileTargetType } from "./types"
/**
* files 模块 Zod 校验 schema
*
* 用于 Server Action 与 API 路由的输入校验,替代手写 typeof 检查与 as 断言。
*/
// FileTargetType 枚举值同步到 Zod保持单一来源types.ts
const FILE_TARGET_TYPES: readonly FileTargetType[] = [
"exam",
"textbook",
"question",
"announcement",
"homework",
"user_avatar",
"message",
]
export const FileTargetTypeSchema = z.enum(
FILE_TARGET_TYPES as unknown as [FileTargetType, ...FileTargetType[]]
)
/**
* 文件上传元数据校验targetType / targetId 来自 FormData
*
* targetType 可选targetId 仅在 targetType 提供时才校验长度。
*/
export const UploadMetadataSchema = z.object({
targetType: FileTargetTypeSchema.optional().nullable(),
targetId: z
.string()
.trim()
.max(128)
.optional()
.nullable()
.transform((v) => (v && v.length > 0 ? v : null)),
})
export type UploadMetadata = z.infer<typeof UploadMetadataSchema>
/**
* 批量删除请求体校验
*
* - ids 必须为非空字符串数组
* - 单次最多 100 条,防止超长 SQL
* - 每条 id 长度上限 128与 schema.id varchar(128) 一致)
*/
export const BatchDeleteSchema = z.object({
ids: z
.array(z.string().min(1).max(128))
.min(1, "No file ids provided")
.max(100, "Cannot delete more than 100 files at once"),
})
export type BatchDeleteInput = z.infer<typeof BatchDeleteSchema>
/**
* 管理员文件列表筛选参数校验
*
* - mimeType精确或前缀匹配"image/"
* - search文件名模糊匹配
* - limit1..200,默认 100
* - offset>=0默认 0
*/
export const FileListQuerySchema = z.object({
mimeType: z.string().trim().max(128).optional().nullable(),
search: z.string().trim().max(255).optional().nullable(),
limit: z.number().int().min(1).max(200).default(100),
offset: z.number().int().min(0).default(0),
})
export type FileListQuery = z.infer<typeof FileListQuerySchema>
/**
* 文件大小校验(用于客户端/服务端一致校验)
*/
export function validateFileSize(size: number): boolean {
return size > 0 && size <= MAX_FILE_SIZE
}