2026-09-18 16:18:31 +08:00
|
|
|
|
// services/api/src/sync/dto.ts —— 内部同步端点请求 DTO(P2 Task 3
|
|
|
|
|
|
// bootstrap/reconcile;Task 4 增 digest)。
|
|
|
|
|
|
// 契约权威:openapi.yaml [internal](syncBootstrap/syncReconcile/syncDigest)。
|
2026-09-18 15:21:41 +08:00
|
|
|
|
// 经全局 ValidationPipe(whitelist)剥离未知字段;校验失败 400 VALIDATION_FAILED。
|
|
|
|
|
|
import {
|
|
|
|
|
|
IsIn,
|
|
|
|
|
|
IsInt,
|
|
|
|
|
|
IsOptional,
|
|
|
|
|
|
IsString,
|
|
|
|
|
|
Max,
|
|
|
|
|
|
Min,
|
|
|
|
|
|
} from 'class-validator';
|
|
|
|
|
|
|
|
|
|
|
|
/** 契约 SyncEntityType(slot-state 预留——与 openapi enum 同步)。 */
|
|
|
|
|
|
export const SYNC_ENTITY_TYPES = [
|
|
|
|
|
|
'album',
|
|
|
|
|
|
'category',
|
|
|
|
|
|
'photo',
|
|
|
|
|
|
'asset',
|
|
|
|
|
|
'slot-state',
|
|
|
|
|
|
] as const;
|
|
|
|
|
|
|
|
|
|
|
|
/** 契约 BootstrapRequest:albumId 缺省 = 全部相册。 */
|
|
|
|
|
|
export class BootstrapRequestDto {
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
|
@IsString()
|
|
|
|
|
|
albumId?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 契约 ReconcileRequest:必填 entityType/sinceVersion/limit。 */
|
|
|
|
|
|
export class ReconcileRequestDto {
|
|
|
|
|
|
@IsIn(SYNC_ENTITY_TYPES)
|
|
|
|
|
|
entityType!: (typeof SYNC_ENTITY_TYPES)[number];
|
|
|
|
|
|
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
|
@IsString()
|
|
|
|
|
|
albumId?: string;
|
|
|
|
|
|
|
|
|
|
|
|
@IsInt()
|
|
|
|
|
|
@Min(0)
|
|
|
|
|
|
sinceVersion!: number;
|
|
|
|
|
|
|
|
|
|
|
|
@IsInt()
|
|
|
|
|
|
@Min(1)
|
|
|
|
|
|
@Max(1000)
|
|
|
|
|
|
limit!: number;
|
|
|
|
|
|
}
|
2026-09-18 16:18:31 +08:00
|
|
|
|
|
|
|
|
|
|
/** 契约 DigestRequest(Task 4):albumId 缺省 = 全部相册。 */
|
|
|
|
|
|
export class DigestRequestDto {
|
|
|
|
|
|
@IsOptional()
|
|
|
|
|
|
@IsString()
|
|
|
|
|
|
albumId?: string;
|
|
|
|
|
|
}
|