feat(api-detail): isCurrent + setCurrent + màj doc et seeder
- Shared types : ajout isCurrent sur ApiEntry et ApiEntryListItem - Backend entity : colonne is_current (boolean, default true) - Backend service : isCurrent calculé à la création, setCurrent() marque une version comme courante (siblings → false) - Backend controller : POST /api/apis/:id/set-current - Frontend ApiService : méthode setCurrent() - Browse/upload : affichage badge "Courante" via isCurrent - Seeder : données de démo mises à jour - Documentation : api-reference, architecture, local-setup, CLAUDE.md 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:
@@ -29,7 +29,7 @@ Liste les entrées avec filtres optionnels et pagination.
|
||||
|
||||
| Paramètre | Type | Défaut | Description |
|
||||
|-----------|------|--------|-------------|
|
||||
| `search` | string | — | Recherche dans le titre et la description (case-insensitive) |
|
||||
| `search` | string | — | Recherche dans `name`, `provider`, `description`, contacts (case-insensitive) |
|
||||
| `type` | `ASYNCAPI` \| `OPENAPI` | — | Filtre par type |
|
||||
| `categoryId` | UUID | — | Filtre par catégorie |
|
||||
| `page` | number | `1` | Page (min 1) |
|
||||
@@ -41,10 +41,13 @@ Liste les entrées avec filtres optionnels et pagination.
|
||||
"items": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "My API",
|
||||
"title": "Consulter Petstore",
|
||||
"name": "Petstore",
|
||||
"convention": "CONSULTER",
|
||||
"version": "1.0.0",
|
||||
"description": "...",
|
||||
"type": "OPENAPI",
|
||||
"provider": "Équipe Produit",
|
||||
"status": "GENERATED",
|
||||
"categoryId": "uuid-or-null",
|
||||
"createdAt": "2025-01-01T00:00:00.000Z",
|
||||
@@ -57,7 +60,7 @@ Liste les entrées avec filtres optionnels et pagination.
|
||||
}
|
||||
```
|
||||
|
||||
> `items` contient des `ApiEntryListItem` (sans `yamlContent` ni `htmlPath`).
|
||||
> `items` contient des `ApiEntryListItem` (sans `yamlContent`, `htmlPath`, contacts ni `versionMajor/Minor/Patch`).
|
||||
|
||||
---
|
||||
|
||||
@@ -69,15 +72,27 @@ Retourne le détail complet d'une entrée.
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "My API",
|
||||
"title": "Consulter Petstore",
|
||||
"name": "Petstore",
|
||||
"convention": "CONSULTER",
|
||||
"version": "1.0.0",
|
||||
"versionMajor": 1,
|
||||
"versionMinor": 0,
|
||||
"versionPatch": 0,
|
||||
"description": "...",
|
||||
"type": "OPENAPI",
|
||||
"provider": "Équipe Produit",
|
||||
"yamlContent": "openapi: '3.0.0'\n...",
|
||||
"htmlPath": "/app/docs-output/uuid/index.html",
|
||||
"status": "GENERATED",
|
||||
"errorMessage": null,
|
||||
"categoryId": "uuid-or-null",
|
||||
"contactFunctionalName": "Alice Martin",
|
||||
"contactFunctionalEntity": "DSI",
|
||||
"contactFunctionalEmail": "alice@example.com",
|
||||
"contactTechnicalName": "Bob Dupont",
|
||||
"contactTechnicalEntity": "Équipe Backend",
|
||||
"contactTechnicalEmail": "bob@example.com",
|
||||
"createdAt": "2025-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2025-01-01T00:00:00.000Z"
|
||||
}
|
||||
@@ -94,10 +109,20 @@ Met à jour les métadonnées d'une entrée (champs éditables par l'utilisateur
|
||||
**Body JSON** (tous les champs sont optionnels)
|
||||
```json
|
||||
{
|
||||
"title": "New title",
|
||||
"version": "2.0.0",
|
||||
"description": "Updated description",
|
||||
"categoryId": "uuid-or-null"
|
||||
"convention": "CONSULTER",
|
||||
"name": "Nouveau nom",
|
||||
"provider": "Équipe X",
|
||||
"versionMajor": 2,
|
||||
"versionMinor": 0,
|
||||
"versionPatch": 0,
|
||||
"description": "Description mise à jour",
|
||||
"categoryId": "uuid-or-null",
|
||||
"contactFunctionalName": "...",
|
||||
"contactFunctionalEntity": "...",
|
||||
"contactFunctionalEmail": "...",
|
||||
"contactTechnicalName": "...",
|
||||
"contactTechnicalEntity": "...",
|
||||
"contactTechnicalEmail": "..."
|
||||
}
|
||||
```
|
||||
|
||||
@@ -146,7 +171,7 @@ Télécharge le fichier YAML source.
|
||||
|
||||
**Réponse 200**
|
||||
- `Content-Type: application/x-yaml`
|
||||
- `Content-Disposition: attachment; filename="<title>.yaml"`
|
||||
- `Content-Disposition: attachment; filename="<name>.yaml"`
|
||||
- Corps : contenu YAML brut
|
||||
|
||||
**Réponse 404** — entrée introuvable
|
||||
@@ -155,6 +180,52 @@ Télécharge le fichier YAML source.
|
||||
|
||||
## Upload (`/api/uploads`)
|
||||
|
||||
### `POST /api/uploads/validate`
|
||||
|
||||
Valide 1 à 20 fichiers YAML sans créer d'entrée en base. Utilisé pour la validation en temps réel lors de l'upload.
|
||||
|
||||
**Content-Type** : `multipart/form-data`
|
||||
|
||||
**Champs du formulaire**
|
||||
|
||||
| Champ | Type | Requis | Description |
|
||||
|-------|------|--------|-------------|
|
||||
| `files` | file (1 à 20) | Oui | Fichiers YAML (`.yaml` ou `.yml`) |
|
||||
|
||||
**Réponse 200**
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"type": "OPENAPI",
|
||||
"mainFile": "petstore.yaml",
|
||||
"name": "Petstore",
|
||||
"versionMajor": 1,
|
||||
"versionMinor": 0,
|
||||
"versionPatch": 0,
|
||||
"description": "A sample API",
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
En cas d'erreur :
|
||||
```json
|
||||
{
|
||||
"valid": false,
|
||||
"type": null,
|
||||
"mainFile": null,
|
||||
"name": null,
|
||||
"versionMajor": null,
|
||||
"versionMinor": null,
|
||||
"versionPatch": null,
|
||||
"description": null,
|
||||
"errors": [
|
||||
{ "file": "api.yaml", "message": "erreur de syntaxe YAML — unexpected token" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/uploads`
|
||||
|
||||
Crée une nouvelle entrée à partir d'un ou plusieurs fichiers YAML.
|
||||
@@ -167,11 +238,21 @@ Lance la génération de documentation en arrière-plan (fire-and-forget).
|
||||
| Champ | Type | Requis | Description |
|
||||
|-------|------|--------|-------------|
|
||||
| `files` | file (1 à 20) | Oui | Fichiers YAML (`.yaml` ou `.yml`) |
|
||||
| `title` | string | Oui | Titre de l'API |
|
||||
| `version` | string | Oui | Version (ex: `1.0.0`) |
|
||||
| `convention` | `CONSULTER` \| `ENREGISTRER` \| `ETRE_NOTIFIE` | Oui | Convention d'échange |
|
||||
| `name` | string | Oui | Nom de l'API |
|
||||
| `provider` | string | Oui | Fournisseur / équipe responsable |
|
||||
| `versionMajor` | string (number) | Non | Version majeure (défaut: 0) |
|
||||
| `versionMinor` | string (number) | Non | Version mineure (défaut: 0) |
|
||||
| `versionPatch` | string (number) | Non | Version patch (défaut: 0) |
|
||||
| `description` | string | Non | Description libre |
|
||||
| `type` | `ASYNCAPI` \| `OPENAPI` | Non | Type (détecté automatiquement si absent) |
|
||||
| `categoryId` | UUID | Non | Catégorie parente |
|
||||
| `contactFunctionalName` | string | Non | Contact métier — nom |
|
||||
| `contactFunctionalEntity` | string | Non | Contact métier — entité |
|
||||
| `contactFunctionalEmail` | string | Non | Contact métier — email |
|
||||
| `contactTechnicalName` | string | Non | Contact technique — nom |
|
||||
| `contactTechnicalEntity` | string | Non | Contact technique — entité |
|
||||
| `contactTechnicalEmail` | string | Non | Contact technique — email |
|
||||
|
||||
**Détection automatique du type**
|
||||
|
||||
@@ -180,13 +261,13 @@ Le type est détecté à partir du contenu YAML :
|
||||
- Présence de `asyncapi:` en début de ligne → `ASYNCAPI`
|
||||
|
||||
Si plusieurs fichiers sont fournis, le fichier contenant la clé racine est considéré comme le fichier principal.
|
||||
Les autres sont bundlés via `redocly bundle` (OpenAPI) ou `asyncapi bundle` (AsyncAPI).
|
||||
Les autres sont bundlés via `redocly bundle` (OpenAPI) ou `@asyncapi/bundler` (AsyncAPI).
|
||||
|
||||
**Réponse 201** — `ApiEntry` créé avec `status: "PENDING"`
|
||||
|
||||
**Réponse 400**
|
||||
- Aucun fichier fourni
|
||||
- `title` ou `version` manquant
|
||||
- `name` ou `convention` manquant
|
||||
- Fichier non YAML
|
||||
- Type non détectable et non fourni
|
||||
- Aucun fichier principal trouvé dans un upload multi-fichiers
|
||||
@@ -243,8 +324,14 @@ Navigation à la racine : retourne les catégories de premier niveau et les APIs
|
||||
"apis": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "API sans catégorie",
|
||||
...
|
||||
"title": "Consulter API sans catégorie",
|
||||
"name": "API sans catégorie",
|
||||
"convention": "CONSULTER",
|
||||
"version": "1.0.0",
|
||||
"provider": "...",
|
||||
"status": "GENERATED",
|
||||
"categoryId": null,
|
||||
"..."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -331,10 +418,11 @@ Met à jour une catégorie.
|
||||
### `DELETE /api/categories/:id`
|
||||
|
||||
Supprime une catégorie.
|
||||
Les APIs et sous-catégories enfants sont désassociées (`categoryId`/`parentId` mis à null).
|
||||
|
||||
**Réponse 204** — succès (pas de corps)
|
||||
|
||||
**Réponse 400** — le dossier contient des APIs ou des sous-dossiers (vérification applicative avant suppression)
|
||||
|
||||
**Réponse 404** — catégorie introuvable
|
||||
|
||||
---
|
||||
@@ -343,7 +431,7 @@ Les APIs et sous-catégories enfants sont désassociées (`categoryId`/`parentId
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Requête invalide (champ manquant, format incorrect) |
|
||||
| 400 | Requête invalide (champ manquant, format incorrect, suppression non vide) |
|
||||
| 404 | Ressource introuvable |
|
||||
| 500 | Erreur interne serveur |
|
||||
|
||||
@@ -365,3 +453,11 @@ Les APIs et sous-catégories enfants sont désassociées (`categoryId`/`parentId
|
||||
| `PENDING` | Entrée créée, génération de doc en cours |
|
||||
| `GENERATED` | Documentation HTML disponible |
|
||||
| `ERROR` | La génération a échoué (voir `errorMessage`) |
|
||||
|
||||
## Conventions d'échange
|
||||
|
||||
| Convention | Label affiché |
|
||||
|------------|---------------|
|
||||
| `CONSULTER` | Consulter |
|
||||
| `ENREGISTRER` | Enregistrer |
|
||||
| `ETRE_NOTIFIE` | Être notifié |
|
||||
|
||||
Reference in New Issue
Block a user