diff --git a/docsfera.json b/docsfera.json index c978f88..cc4bfd0 100644 --- a/docsfera.json +++ b/docsfera.json @@ -5947,6 +5947,16 @@ } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateColumnsMetadataRequest" + } + } + } + }, "responses": { "200": { "description": "" @@ -11162,6 +11172,35 @@ "columns_metadata" ] }, + "ColumnDescriptionDto": { + "type": "object", + "properties": { + "column_name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "column_name", + "description" + ] + }, + "UpdateColumnsMetadataRequest": { + "type": "object", + "properties": { + "columns": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ColumnDescriptionDto" + } + } + }, + "required": [ + "columns" + ] + }, "IData": { "type": "object", "properties": { diff --git a/src/modules/catalog/catalog.controller.ts b/src/modules/catalog/catalog.controller.ts index 9484f1b..1690e58 100644 --- a/src/modules/catalog/catalog.controller.ts +++ b/src/modules/catalog/catalog.controller.ts @@ -52,6 +52,7 @@ import { IUpdateDataRequest, TriggerCatalogReq, TriggerCatalogRes, + UpdateColumnsMetadataRequest, } from './dtos'; import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter'; import { Language } from 'src/decorators/language.decorator'; @@ -441,35 +442,14 @@ export class CatalogController { @User() user: RequestUser, @Language() language: LanguageEnum, @Param('id') id: string, - @Body() - body: { - column_name?: string; - description?: string; - columns?: { column_name: string; description: string }[]; - }, + @Body(new ValidationPipe()) body: UpdateColumnsMetadataRequest, ): Promise<{ success: boolean }> { const { customer_name, customer_id, user_id, username } = user; - // Accept both a single { column_name, description } and a batch { columns: [...] }. - const columns = Array.isArray(body.columns) - ? body.columns - : [{ column_name: body.column_name, description: body.description }]; - - // column_name and description must be strings — the frontend renders the - // description as text and breaks on non-string values (e.g. numbers). - for (const column of columns) { - if (typeof column?.column_name !== 'string' || !column.column_name.trim()) { - throw new BadRequestException('column_name must be a non-empty string'); - } - if (typeof column?.description !== 'string') { - throw new BadRequestException('description must be a string'); - } - } - this.logger.info(`/catalog - update columns metadata`, { user_id, customer_name, - columns_count: columns.length, + columns_count: body.columns.length, }); const metadata = PackTheMetadata({ @@ -480,7 +460,11 @@ export class CatalogController { language, }); - await this.catalogService.updateColumnsDescriptions(id, columns, metadata); + await this.catalogService.updateColumnsDescriptions( + id, + body.columns, + metadata, + ); return { success: true }; } diff --git a/src/modules/catalog/dtos/index.ts b/src/modules/catalog/dtos/index.ts index 770b01c..6b71473 100644 --- a/src/modules/catalog/dtos/index.ts +++ b/src/modules/catalog/dtos/index.ts @@ -1,5 +1,13 @@ import { ApiProperty, ApiPropertyOptional, PickType } from '@nestjs/swagger'; -import { IsEnum } from 'class-validator'; +import { + ArrayNotEmpty, + IsArray, + IsEnum, + IsNotEmpty, + IsString, + ValidateNested, +} from 'class-validator'; +import { Type } from 'class-transformer'; import { CreateDataAssetRequest } from '@dadosfera/protospack-v2/dist/lib/Catalog/interfaces/messages'; export enum DataAssetShareType { @@ -219,6 +227,26 @@ export class IUpdateCertificationStatusRequest { certification_status: CertificationStatus; } +export class ColumnDescriptionDto { + @ApiProperty() + @IsString() + @IsNotEmpty() + column_name: string; + + @ApiProperty() + @IsString() + description: string; +} + +export class UpdateColumnsMetadataRequest { + @ApiProperty({ type: [ColumnDescriptionDto] }) + @IsArray() + @ArrayNotEmpty() + @ValidateNested({ each: true }) + @Type(() => ColumnDescriptionDto) + columns: ColumnDescriptionDto[]; +} + export class ICreateDataAsset implements CreateDataAssetRequest { @ApiProperty() display_name: string;