Files
auto-virtual-tryon-frontend/src/lib/validation/library-resource.ts
2026-03-28 13:42:22 +08:00

151 lines
4.7 KiB
TypeScript

import { z } from "zod";
import { RouteError } from "@/lib/http/response";
export const backendLibraryResourceTypeSchema = z.enum(["model", "scene", "garment"]);
export const backendLibraryFileRoleSchema = z.enum(["original", "thumbnail", "gallery"]);
const presignUploadSchema = z.object({
resourceType: backendLibraryResourceTypeSchema,
fileRole: backendLibraryFileRoleSchema,
fileName: z.string().trim().min(1),
contentType: z.string().trim().min(1),
});
const createLibraryFileSchema = z.object({
fileRole: backendLibraryFileRoleSchema,
storageKey: z.string().trim().min(1),
publicUrl: z.string().trim().min(1),
mimeType: z.string().trim().min(1),
sizeBytes: z.number().int().nonnegative(),
sortOrder: z.number().int().nonnegative().default(0),
width: z.number().int().positive().optional(),
height: z.number().int().positive().optional(),
});
const createLibraryResourceSchema = z.object({
name: z.string().trim().min(1),
description: z.string().trim().optional().default(""),
tags: z.array(z.string().trim()).default([]),
gender: z.string().trim().optional(),
ageGroup: z.string().trim().optional(),
poseId: z.number().int().positive().optional(),
environment: z.string().trim().optional(),
category: z.string().trim().optional(),
files: z.array(createLibraryFileSchema).min(2),
});
const updateLibraryResourceSchema = z
.object({
name: z.string().trim().min(1).optional(),
description: z.string().trim().optional(),
tags: z.array(z.string().trim()).optional(),
gender: z.string().trim().optional(),
ageGroup: z.string().trim().optional(),
poseId: z.number().int().positive().optional(),
environment: z.string().trim().optional(),
category: z.string().trim().optional(),
coverFileId: z.number().int().positive().optional(),
})
.refine((value) => Object.keys(value).length > 0, {
message: "至少提供一个可更新字段。",
});
export type CreateLibraryResourcePayload = z.infer<typeof createLibraryResourceSchema>;
export type UpdateLibraryResourcePayload = z.infer<typeof updateLibraryResourceSchema>;
export function parseLibraryUploadPresignPayload(payload: unknown) {
const result = presignUploadSchema.safeParse(payload);
if (!result.success) {
throw new RouteError(
400,
"VALIDATION_ERROR",
"上传参数不合法。",
result.error.flatten(),
);
}
return {
resource_type: result.data.resourceType,
file_role: result.data.fileRole,
file_name: result.data.fileName,
content_type: result.data.contentType,
};
}
export function parseCreateLibraryResourcePayload(
payload: unknown,
resourceType: z.infer<typeof backendLibraryResourceTypeSchema>,
) {
const result = createLibraryResourceSchema.safeParse(payload);
if (!result.success) {
throw new RouteError(
400,
"VALIDATION_ERROR",
"资源参数不合法。",
result.error.flatten(),
);
}
return {
resource_type: resourceType,
name: result.data.name,
description: result.data.description,
tags: result.data.tags.filter(Boolean),
gender: result.data.gender,
age_group: result.data.ageGroup,
pose_id: result.data.poseId,
environment: result.data.environment,
category: result.data.category,
files: result.data.files.map((file) => ({
file_role: file.fileRole,
storage_key: file.storageKey,
public_url: file.publicUrl,
mime_type: file.mimeType,
size_bytes: file.sizeBytes,
sort_order: file.sortOrder,
width: file.width,
height: file.height,
})),
};
}
export function parseUpdateLibraryResourcePayload(payload: unknown) {
const result = updateLibraryResourceSchema.safeParse(payload);
if (!result.success) {
throw new RouteError(
400,
"VALIDATION_ERROR",
"资源更新参数不合法。",
result.error.flatten(),
);
}
return {
...(result.data.name !== undefined ? { name: result.data.name } : {}),
...(result.data.description !== undefined
? { description: result.data.description }
: {}),
...(result.data.tags !== undefined
? { tags: result.data.tags.filter(Boolean) }
: {}),
...(result.data.gender !== undefined ? { gender: result.data.gender } : {}),
...(result.data.ageGroup !== undefined
? { age_group: result.data.ageGroup }
: {}),
...(result.data.poseId !== undefined ? { pose_id: result.data.poseId } : {}),
...(result.data.environment !== undefined
? { environment: result.data.environment }
: {}),
...(result.data.category !== undefined
? { category: result.data.category }
: {}),
...(result.data.coverFileId !== undefined
? { cover_file_id: result.data.coverFileId }
: {}),
};
}