feat: refonte métadonnées API + UX dossiers et import
- Nouveau schéma api_entries : convention+name, version X.X.X, provider, contacts splitées (name/entity/email), suppression des anciens champs - Formulaire upload étape 2 : convention+nom, version 3 champs, fournisseur, contacts métier et technique obligatoires ; type détecté auto → select désactivé - Validation YAML : redocly.yaml (extends: spec), support noms avec espaces, extraction métadonnées (name, version, description) depuis info YAML - Dossiers : modale création avec champ Emplacement pré-initialisé depuis le contexte de navigation, options └ avec indentation par profondeur - Import depuis un dossier : pré-sélection de la catégorie via queryParam - Recherche étendue : name, provider, description, contacts - Résolution @datacat/shared via workspace:* + compilation CJS avant NestJS Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
@@ -4,14 +4,11 @@ import { Repository } from 'typeorm';
|
||||
import { ApiEntryEntity } from './api-entry.entity';
|
||||
import { CreateApiEntryDto } from './dto/create-api-entry.dto';
|
||||
import { UpdateApiEntryDto } from './dto/update-api-entry.dto';
|
||||
import { ApiListResponse, ApiListQuery, ApiEntry, ApiEntryListItem, ApiType, ApiStatus } from '@datacat/shared';
|
||||
import { ApiListResponse, ApiListQuery, ApiEntry, ApiEntryListItem, ApiType, ApiStatus, ApiConvention, API_CONVENTION_LABELS } from '@datacat/shared';
|
||||
import { DocsGenerationService } from '../docs-generation/docs-generation.service';
|
||||
|
||||
/** Champs internes mis à jour par DocsGenerationService */
|
||||
interface InternalUpdateFields {
|
||||
title?: string;
|
||||
version?: string;
|
||||
description?: string;
|
||||
htmlPath?: string | null;
|
||||
status?: ApiStatus;
|
||||
errorMessage?: string | null;
|
||||
@@ -28,19 +25,23 @@ export class ApisService {
|
||||
|
||||
async create(dto: CreateApiEntryDto): Promise<ApiEntry> {
|
||||
const entity = this.repo.create({
|
||||
title: dto.title,
|
||||
version: dto.version,
|
||||
convention: dto.convention,
|
||||
name: dto.name,
|
||||
provider: dto.provider,
|
||||
versionMajor: dto.versionMajor,
|
||||
versionMinor: dto.versionMinor,
|
||||
versionPatch: dto.versionPatch,
|
||||
description: dto.description ?? null,
|
||||
type: dto.type,
|
||||
yamlContent: dto.yamlContent,
|
||||
status: 'PENDING',
|
||||
categoryId: dto.categoryId ?? null,
|
||||
functionalDoc: dto.functionalDoc ?? null,
|
||||
technicalDoc: dto.technicalDoc ?? null,
|
||||
externalDocUrl: dto.externalDocUrl ?? null,
|
||||
contactFunctional: dto.contactFunctional ?? null,
|
||||
contactTechnical: dto.contactTechnical ?? null,
|
||||
accessRights: dto.accessRights ?? null,
|
||||
contactFunctionalName: dto.contactFunctionalName,
|
||||
contactFunctionalEntity: dto.contactFunctionalEntity,
|
||||
contactFunctionalEmail: dto.contactFunctionalEmail,
|
||||
contactTechnicalName: dto.contactTechnicalName,
|
||||
contactTechnicalEntity: dto.contactTechnicalEntity,
|
||||
contactTechnicalEmail: dto.contactTechnicalEmail,
|
||||
});
|
||||
const saved = await this.repo.save(entity);
|
||||
return toApiEntry(saved);
|
||||
@@ -58,7 +59,11 @@ export class ApisService {
|
||||
}
|
||||
if (query.search) {
|
||||
qb.andWhere(
|
||||
'(LOWER(api.title) LIKE :search OR LOWER(api.description) LIKE :search)',
|
||||
`(LOWER(api.name) LIKE :search
|
||||
OR LOWER(api.provider) LIKE :search
|
||||
OR LOWER(COALESCE(api.description, '')) LIKE :search
|
||||
OR LOWER(api.contact_functional_name) LIKE :search
|
||||
OR LOWER(api.contact_technical_name) LIKE :search)`,
|
||||
{ search: `%${query.search.toLowerCase()}%` },
|
||||
);
|
||||
}
|
||||
@@ -109,24 +114,38 @@ export class ApisService {
|
||||
}
|
||||
}
|
||||
|
||||
function buildTitle(convention: ApiConvention, name: string): string {
|
||||
return `${API_CONVENTION_LABELS[convention]} ${name}`;
|
||||
}
|
||||
|
||||
function buildVersion(major: number, minor: number, patch: number): string {
|
||||
return `${major}.${minor}.${patch}`;
|
||||
}
|
||||
|
||||
function toApiEntry(entity: ApiEntryEntity): ApiEntry {
|
||||
return {
|
||||
id: entity.id,
|
||||
title: entity.title,
|
||||
version: entity.version,
|
||||
title: buildTitle(entity.convention, entity.name),
|
||||
name: entity.name,
|
||||
convention: entity.convention,
|
||||
version: buildVersion(entity.versionMajor, entity.versionMinor, entity.versionPatch),
|
||||
versionMajor: entity.versionMajor,
|
||||
versionMinor: entity.versionMinor,
|
||||
versionPatch: entity.versionPatch,
|
||||
description: entity.description,
|
||||
type: entity.type,
|
||||
provider: entity.provider,
|
||||
yamlContent: entity.yamlContent,
|
||||
htmlPath: entity.htmlPath,
|
||||
status: entity.status,
|
||||
errorMessage: entity.errorMessage,
|
||||
categoryId: entity.categoryId,
|
||||
functionalDoc: entity.functionalDoc,
|
||||
technicalDoc: entity.technicalDoc,
|
||||
externalDocUrl: entity.externalDocUrl,
|
||||
contactFunctional: entity.contactFunctional,
|
||||
contactTechnical: entity.contactTechnical,
|
||||
accessRights: entity.accessRights,
|
||||
contactFunctionalName: entity.contactFunctionalName,
|
||||
contactFunctionalEntity: entity.contactFunctionalEntity,
|
||||
contactFunctionalEmail: entity.contactFunctionalEmail,
|
||||
contactTechnicalName: entity.contactTechnicalName,
|
||||
contactTechnicalEntity: entity.contactTechnicalEntity,
|
||||
contactTechnicalEmail: entity.contactTechnicalEmail,
|
||||
createdAt: entity.createdAt.toISOString(),
|
||||
updatedAt: entity.updatedAt.toISOString(),
|
||||
};
|
||||
@@ -135,10 +154,13 @@ function toApiEntry(entity: ApiEntryEntity): ApiEntry {
|
||||
function toApiEntryListItem(entity: ApiEntryEntity): ApiEntryListItem {
|
||||
return {
|
||||
id: entity.id,
|
||||
title: entity.title,
|
||||
version: entity.version,
|
||||
title: buildTitle(entity.convention, entity.name),
|
||||
name: entity.name,
|
||||
convention: entity.convention,
|
||||
version: buildVersion(entity.versionMajor, entity.versionMinor, entity.versionPatch),
|
||||
description: entity.description,
|
||||
type: entity.type,
|
||||
provider: entity.provider,
|
||||
status: entity.status,
|
||||
categoryId: entity.categoryId,
|
||||
createdAt: entity.createdAt.toISOString(),
|
||||
|
||||
Reference in New Issue
Block a user