2026-05-05 13:25:28 +03:00
import { Body , Controller , Get , Param , Post , Query } from "@nestjs/common"
import {
ApiBadRequestResponse ,
ApiConflictResponse ,
ApiCreatedResponse ,
ApiNotFoundResponse ,
ApiOkResponse ,
ApiOperation ,
ApiParam ,
ApiQuery ,
ApiTags ,
} from "@nestjs/swagger"
import { AssetsService } from "./assets.service"
import { AssetResponseDto , AssetVariantsResponseDto , AssetsListResponseDto } from "./asset-response.dto"
2026-05-05 13:31:45 +03:00
import { CreateAssetVersionRequestDto , CreateAssetVersionResponseDto } from "./create-asset-version.dto"
2026-05-05 13:25:28 +03:00
import { CreateAssetVariantsRequestDto , CreateAssetVariantsResponseDto } from "./create-asset-variants.dto"
import { CreateAssetRequestDto , CreateAssetResponseDto } from "./create-asset.dto"
@ApiTags ( "assets" )
@Controller ( "assets" )
export class AssetsController {
constructor ( private readonly assets : AssetsService ) { }
@Get ( )
@ApiOperation ( {
summary : "получить список assets" ,
description : "Возвращает последние зарегистрированные assets вместе с source URL текущей версии." ,
} )
@ApiQuery ( { description : "Максимальное количество assets в ответе." , example : 50 , name : "limit" , required : false } )
@ApiQuery ( { description : "Смещение для простого paging." , example : 0 , name : "offset" , required : false } )
@ApiOkResponse ( { description : "Список assets возвращён." , type : AssetsListResponseDto } )
listAssets ( @Query ( "limit" ) limit? : string , @Query ( "offset" ) offset? : string ) : Promise < AssetsListResponseDto > {
return this . assets . listAssets ( { limit , offset } )
}
@Post ( )
@ApiOperation ( {
summary : "зарегистрировать исходное изображение" ,
description :
"Создаёт asset и первую версию source image. Source URL сохраняется в PostgreSQL, а публичный image URL строится через Gateway без раскрытия исходной ссылки клиенту." ,
} )
@ApiCreatedResponse ( { description : "Asset создан, версия source image зарегистрирована." , type : CreateAssetResponseDto } )
@ApiBadRequestResponse ( { description : "Некорректный sourceUrl, publicId или source host запрещён настройками." } )
@ApiConflictResponse ( { description : "Asset с таким publicId уже существует." } )
createAsset ( @Body ( ) request : CreateAssetRequestDto ) : Promise < CreateAssetResponseDto > {
return this . assets . createAsset ( request )
}
@Get ( ":publicId" )
@ApiOperation ( {
summary : "получить asset по publicId" ,
description : "Возвращает metadata asset и source URL текущей версии." ,
} )
@ApiParam ( { description : "Публичный идентификатор asset." , example : "asset_demo" , name : "publicId" } )
@ApiOkResponse ( { description : "Asset найден." , type : AssetResponseDto } )
@ApiNotFoundResponse ( { description : "Asset не найден." } )
getAsset ( @Param ( "publicId" ) publicId : string ) : Promise < AssetResponseDto > {
return this . assets . getAsset ( publicId )
}
2026-05-05 13:31:45 +03:00
@Post ( ":publicId/versions" )
@ApiOperation ( {
summary : "создать новую версию source image" ,
description :
"Регистрирует новый source URL для существующего asset, увеличивает currentVersion и тем самым создаёт новый immutable Gateway URL `/v{version}` без purge старых URLs." ,
} )
@ApiParam ( { description : "Публичный идентификатор asset." , example : "asset_demo" , name : "publicId" } )
@ApiCreatedResponse ( { description : "Новая версия source image создана и стала текущей." , type : CreateAssetVersionResponseDto } )
@ApiBadRequestResponse ( { description : "Некорректный sourceUrl или source host запрещён настройками." } )
@ApiConflictResponse ( { description : "Версия asset изменилась конкурентно." } )
@ApiNotFoundResponse ( { description : "Asset не найден." } )
createAssetVersion (
@Param ( "publicId" ) publicId : string ,
@Body ( ) request : CreateAssetVersionRequestDto ,
) : Promise < CreateAssetVersionResponseDto > {
return this . assets . createAssetVersion ( publicId , request )
}
2026-05-05 13:25:28 +03:00
@Get ( ":publicId/variants" )
@ApiOperation ( {
summary : "получить variants asset" ,
description : "Возвращает variants asset: preset/custom параметры, status, S3 key, public URL и ошибку генерации, если она была." ,
} )
@ApiParam ( { description : "Публичный идентификатор asset." , example : "asset_demo" , name : "publicId" } )
@ApiQuery ( { description : "Версия source image. Если не передана, возвращаются variants всех версий." , example : 1 , name : "version" , required : false } )
@ApiOkResponse ( { description : "Variants возвращены." , type : AssetVariantsResponseDto } )
@ApiNotFoundResponse ( { description : "Asset не найден." } )
listAssetVariants (
@Param ( "publicId" ) publicId : string ,
@Query ( "version" ) version? : string ,
) : Promise < AssetVariantsResponseDto > {
return this . assets . listAssetVariants ( publicId , version )
}
@Post ( ":publicId/variants" )
@ApiOperation ( {
summary : "поставить generation jobs для variants" ,
description :
"Business endpoint для явной подготовки variants. В режиме `single` создаёт один variant, в режиме `family` создаёт набор variants preset по всем разрешённым widths/formats. Endpoint не ждёт bytes, а возвращает созданные/переиспользованные rows и public URLs." ,
} )
@ApiParam ( { description : "Публичный идентификатор asset." , example : "asset_demo" , name : "publicId" } )
@ApiCreatedResponse ( { description : "Variants созданы или переиспользованы, jobs поставлены при необходимости." , type : CreateAssetVariantsResponseDto } )
@ApiBadRequestResponse ( { description : "Некорректный preset/custom transform config." } )
@ApiNotFoundResponse ( { description : "Asset или version не найдены." } )
createAssetVariants (
@Param ( "publicId" ) publicId : string ,
@Body ( ) request : CreateAssetVariantsRequestDto ,
) : Promise < CreateAssetVariantsResponseDto > {
return this . assets . createAssetVariants ( publicId , request )
}
}