feat: добавить генерацию image variants

- добавлен shared config presets, custom transforms и allowlist hosts
- реализованы Backend endpoints для assets, presets и variants
- добавлена orchestration через PostgreSQL, RabbitMQ, S3 и worker
- обновлён Gateway read-through flow с L1 cache и корректным Vary: Accept
- добавлена миграция resize_mode для variants lookup
- обновлены dev scripts, env template, lockfile и документация
This commit is contained in:
2026-05-05 13:25:28 +03:00
parent bcadb85a83
commit 1c0e8277a3
59 changed files with 3526 additions and 143 deletions

View File

@@ -0,0 +1,58 @@
import { ApiProperty } from "@nestjs/swagger"
export class PresetResponseDto {
@ApiProperty({ description: "Имя preset.", example: "card" })
name!: string
@ApiProperty({ description: "Режим preset.", enum: ["fixed", "responsive"], example: "responsive" })
mode!: string
@ApiProperty({ description: "Разрешённые форматы.", example: ["avif", "webp", "jpg"] })
formats!: readonly string[]
@ApiProperty({ description: "Разрешённые значения quality.", example: [75, 80] })
qualities!: readonly number[]
@ApiProperty({ description: "Quality по умолчанию.", example: 80 })
quality!: number
@ApiProperty({ description: "Resize mode preset.", enum: ["fit", "fill"], example: "fit" })
resize!: string
@ApiProperty({ description: "Фиксированная ширина для fixed preset.", example: 256, required: false })
width?: number
@ApiProperty({ description: "Фиксированная высота для fixed preset.", example: 256, required: false })
height?: number
@ApiProperty({ description: "Разрешённые ширины для responsive preset.", example: [320, 640, 960], required: false })
widths?: readonly number[]
}
export class CustomTransformConfigResponseDto {
@ApiProperty({ description: "Включены ли custom transforms.", example: true })
enabled!: boolean
@ApiProperty({ description: "Разрешённые форматы custom transforms.", example: ["avif", "webp", "jpg", "png"] })
formats!: readonly string[]
@ApiProperty({ description: "Максимальная ширина custom transform.", example: 4096 })
maxWidth!: number
@ApiProperty({ description: "Максимальная высота custom transform.", example: 4096 })
maxHeight!: number
@ApiProperty({ description: "Quality по умолчанию для custom transform.", example: 80 })
quality!: number
}
export class PresetsResponseDto {
@ApiProperty({ description: "Static presets.", type: [PresetResponseDto] })
presets!: PresetResponseDto[]
@ApiProperty({ description: "Custom transform config.", type: CustomTransformConfigResponseDto })
custom!: CustomTransformConfigResponseDto
@ApiProperty({ description: "Mock allowlist source hosts.", example: ["storage.yandexcloud.net"] })
allowedSourceHosts!: string[]
}