From 65fa6939860cdb8067ca72aa855f6fd263e6ca96 Mon Sep 17 00:00:00 2001 From: Kerboul Date: Sun, 27 Apr 2025 01:20:27 +0200 Subject: [PATCH] =?UTF-8?q?feat(api):=20Am=C3=A9liorer=20la=20documentatio?= =?UTF-8?q?n=20Swagger=20pour=20les=20routes=20de=20l'API,=20ajout=20de=20?= =?UTF-8?q?descriptions=20d=C3=A9taill=C3=A9es=20et=20de=20sch=C3=A9mas=20?= =?UTF-8?q?pour=20les=20entit=C3=A9s=20Project,=20Measurement,=20Video,=20?= =?UTF-8?q?Camera,=20et=20Error.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/index.js | 117 ++++++++++++++++++++++++++++++-- src/routes/cameraRoutes.js | 98 +++++++++++++++++++++----- src/routes/imageRoutes.js | 98 +++++++++++++++++++++----- src/routes/measurementRoutes.js | 63 +++++++++++++---- src/routes/projectRoutes.js | 96 ++++++++++++++++++++++---- src/routes/videoRoutes.js | 100 ++++++++++++++++++++++----- 6 files changed, 485 insertions(+), 87 deletions(-) diff --git a/src/config/index.js b/src/config/index.js index e848be1..a2f29ed 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -29,16 +29,121 @@ module.exports = { definition: { openapi: '3.0.0', info: { - title: 'API Documentation', + title: 'API Timelapse', version: '1.0.0', - description: 'Documentation de l\'API avec Swagger' + description: 'Documentation de l\'API Timelapse pour la gestion des projets, mesures et vidéos', + contact: { + name: 'Support Timelapse', + email: 'support@timelapse.kerboul.me' + } }, servers: [ - { url: 'https://timelapse.kerboul.me/api' }, - { url: 'http://localhost:3000/api' } - ] + { url: 'https://timelapse.kerboul.me/api', description: 'Serveur de production' }, + { url: 'http://localhost:3000/api', description: 'Serveur de développement local' } + ], + components: { + schemas: { + Project: { + type: 'object', + properties: { + id: { type: 'integer' }, + name: { type: 'string' }, + description: { type: 'string' }, + start_date: { type: 'string', format: 'date' }, + status: { type: 'integer' } + } + }, + Measurement: { + type: 'object', + properties: { + id: { type: 'integer' }, + project_id: { type: 'integer' }, + timestamp: { type: 'string', format: 'date-time' }, + path: { type: 'string' }, + temperature: { type: 'number' }, + humidity: { type: 'number' }, + order_id: { type: 'integer' } + } + }, + Video: { + type: 'object', + properties: { + id: { type: 'integer' }, + project_id: { type: 'integer' }, + measurement_ids: { type: 'string' }, + name: { type: 'string' }, + resolution: { type: 'string' }, + duration: { type: 'integer' }, + status: { type: 'integer' }, + progress: { type: 'number' }, + video_file: { type: 'string', nullable: true }, + started_at: { type: 'string', format: 'date-time', nullable: true }, + updated_at: { type: 'string', format: 'date-time', nullable: true }, + eta: { type: 'number', nullable: true } + } + }, + Camera: { + type: 'object', + properties: { + id: { type: 'integer' }, + interval: { type: 'integer', nullable: true }, + maintenance: { type: 'integer' }, + active: { type: 'integer' } + } + }, + Error: { + type: 'object', + properties: { + message: { type: 'string' }, + statusCode: { type: 'integer' }, + details: { type: 'string', nullable: true }, + timestamp: { type: 'string', format: 'date-time' } + } + } + }, + responses: { + NotFound: { + description: 'La ressource demandée n\'a pas été trouvée', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/Error' + } + } + } + }, + BadRequest: { + description: 'Requête invalide', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/Error' + } + } + } + }, + ServerError: { + description: 'Erreur serveur', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/Error' + } + } + } + } + } + }, + tags: [ + { name: 'Projets', description: 'Opérations relatives aux projets' }, + { name: 'Mesures', description: 'Opérations relatives aux mesures et images' }, + { name: 'Vidéos', description: 'Opérations relatives aux vidéos' }, + { name: 'Caméra', description: 'Opérations relatives au contrôle de la caméra' }, + { name: 'Images', description: 'Opérations relatives aux images' }, + { name: 'Système', description: 'Opérations relatives au système' } + ], }, - apis: ['./src/routes/*.js', './src/controllers/*.js'] // Chemins pour la documentation + apis: ['./src/routes/*.js'] // Chemins pour la documentation }, // Chemins des répertoires diff --git a/src/routes/cameraRoutes.js b/src/routes/cameraRoutes.js index 8e87201..71c198b 100644 --- a/src/routes/cameraRoutes.js +++ b/src/routes/cameraRoutes.js @@ -7,26 +7,19 @@ const CameraController = require('../controllers/cameraController'); * @swagger * /camera/status: * get: + * tags: + * - Caméra * summary: Récupère le statut actuel de la caméra + * description: Retourne les paramètres et l'état actuel du système de caméra * responses: * 200: * description: Statut de la caméra * content: * application/json: * schema: - * type: object - * properties: - * id: - * type: integer - * interval: - * type: integer - * nullable: true - * maintenance: - * type: integer - * active: - * type: integer + * $ref: '#/components/schemas/Camera' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/camera/status', CameraController.getCameraStatus); @@ -34,7 +27,10 @@ router.get('/camera/status', CameraController.getCameraStatus); * @swagger * /procedure/start: * post: + * tags: + * - Caméra * summary: Démarre une procédure de capture + * description: Démarre une nouvelle procédure de capture d'images à intervalle régulier * requestBody: * required: true * content: @@ -44,10 +40,15 @@ router.get('/camera/status', CameraController.getCameraStatus); * properties: * project_id: * type: integer + * description: ID du projet pour lequel les images seront capturées * interval: * type: integer + * description: Intervalle entre deux captures (en secondes) + * example: 30 * nb_images: * type: integer + * description: Nombre total d'images à capturer + * example: 48 * required: * - project_id * - interval @@ -55,10 +56,27 @@ router.get('/camera/status', CameraController.getCameraStatus); * responses: * 200: * description: Procédure démarrée avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Procédure de capture démarrée avec succès + * settings: + * type: object + * properties: + * interval: + * type: integer + * example: 30 + * nb_images: + * type: integer + * example: 48 * 400: - * description: Paramètres invalides ou procédure déjà en cours + * $ref: '#/components/responses/BadRequest' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/procedure/start', CameraController.startProcedure); @@ -66,12 +84,23 @@ router.post('/procedure/start', CameraController.startProcedure); * @swagger * /procedure/stop: * post: + * tags: + * - Caméra * summary: Initie l'arrêt d'une procédure de capture + * description: Indique au système de caméra d'arrêter la procédure de capture en cours dès que possible * responses: * 200: * description: Procédure d'arrêt initiée + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Procédure d'arrêt de la caméra initiée avec succès * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/procedure/stop', CameraController.stopProcedure); @@ -79,12 +108,23 @@ router.post('/procedure/stop', CameraController.stopProcedure); * @swagger * /camera/stop: * post: + * tags: + * - Caméra * summary: Confirme l'arrêt de la caméra + * description: Confirme que la caméra a bien été arrêtée (appelé par la caméra) * responses: * 200: * description: Caméra arrêtée avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Caméra arrêtée avec succès * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/camera/stop', CameraController.confirmStopProcedure); @@ -92,12 +132,23 @@ router.post('/camera/stop', CameraController.confirmStopProcedure); * @swagger * /camera/maintenance: * post: + * tags: + * - Caméra * summary: Active le mode maintenance + * description: Place la caméra en mode maintenance pour empêcher les captures programmées * responses: * 200: * description: Mode maintenance activé + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Caméra en mode maintenance * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/camera/maintenance', CameraController.activateMaintenance); @@ -105,12 +156,23 @@ router.post('/camera/maintenance', CameraController.activateMaintenance); * @swagger * /camera/maintenance/deactivate: * post: + * tags: + * - Caméra * summary: Désactive le mode maintenance + * description: Désactive le mode maintenance et permet à la caméra de reprendre les captures programmées * responses: * 200: * description: Mode maintenance désactivé + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Caméra sortie du mode maintenance * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/camera/maintenance/deactivate', CameraController.deactivateMaintenance); diff --git a/src/routes/imageRoutes.js b/src/routes/imageRoutes.js index edfe75d..5c5f084 100644 --- a/src/routes/imageRoutes.js +++ b/src/routes/imageRoutes.js @@ -11,14 +11,23 @@ const upload = multer({ storage: multer.memoryStorage() }); * @swagger * /smile: * get: + * tags: + * - Images + * - Système * summary: Récupère une image de test (smile) + * description: Endpoint de test qui retourne une image statique * responses: * 200: * description: Image de test + * content: + * image/png: + * schema: + * type: string + * format: binary * 404: - * description: Image non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/smile', ImageController.getSmileImage); @@ -26,7 +35,10 @@ router.get('/smile', ImageController.getSmileImage); * @swagger * /images/{projectId}/{orderId}: * get: + * tags: + * - Images * summary: Récupère une image par projet ID et ordre ID + * description: Télécharge l'image associée à un projet et un numéro d'ordre spécifique * parameters: * - in: path * name: projectId @@ -39,16 +51,21 @@ router.get('/smile', ImageController.getSmileImage); * required: true * schema: * type: integer - * description: ID d'ordre + * description: ID d'ordre séquentiel de l'image * responses: * 200: - * description: Image + * description: Image (fichier) + * content: + * image/jpeg: + * schema: + * type: string + * format: binary * 400: - * description: IDs invalides + * $ref: '#/components/responses/BadRequest' * 404: - * description: Image non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/images/:projectId/:orderId', ImageController.getImageByProjectAndOrderId); @@ -56,7 +73,10 @@ router.get('/images/:projectId/:orderId', ImageController.getImageByProjectAndOr * @swagger * /images/{measurementId}: * get: + * tags: + * - Images * summary: Récupère une image par ID de mesure + * description: Télécharge l'image associée à une mesure spécifique * parameters: * - in: path * name: measurementId @@ -66,13 +86,18 @@ router.get('/images/:projectId/:orderId', ImageController.getImageByProjectAndOr * description: ID de la mesure * responses: * 200: - * description: Image + * description: Image (fichier) + * content: + * image/jpeg: + * schema: + * type: string + * format: binary * 400: - * description: ID invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Image non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/images/:measurementId', ImageController.getImageByMeasurementId); @@ -80,7 +105,10 @@ router.get('/images/:measurementId', ImageController.getImageByMeasurementId); * @swagger * /preview/{projectId}/{orderId}: * get: + * tags: + * - Images * summary: Récupère un aperçu d'une image + * description: Retourne une version redimensionnée (miniature) d'une image * parameters: * - in: path * name: projectId @@ -93,16 +121,21 @@ router.get('/images/:measurementId', ImageController.getImageByMeasurementId); * required: true * schema: * type: integer - * description: ID d'ordre + * description: ID d'ordre séquentiel de l'image * responses: * 200: * description: Aperçu d'image redimensionné + * content: + * image/jpeg: + * schema: + * type: string + * format: binary * 400: - * description: IDs invalides + * $ref: '#/components/responses/BadRequest' * 404: - * description: Image non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/preview/:projectId/:orderId', ImageController.getImagePreview); @@ -110,7 +143,11 @@ router.get('/preview/:projectId/:orderId', ImageController.getImagePreview); * @swagger * /camera/upload: * post: + * tags: + * - Images + * - Caméra * summary: Télécharge une image avec données de mesure + * description: Enregistre une nouvelle image capturée avec les données de mesure associées * requestBody: * required: true * content: @@ -121,22 +158,49 @@ router.get('/preview/:projectId/:orderId', ImageController.getImagePreview); * image: * type: string * format: binary + * description: Fichier image à télécharger * projectId: * type: integer + * description: ID du projet associé * timestamp: * type: string * format: date-time + * description: Horodatage de la capture * temperature: * type: number + * description: Température mesurée + * example: 22.5 * humidity: * type: number + * description: Humidité mesurée + * example: 45.2 + * required: + * - image + * - projectId + * - timestamp + * - temperature + * - humidity * responses: * 200: * description: Image téléchargée avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Mesure téléchargée avec succès + * path: + * type: string + * example: /storage/1/images/42.jpg + * id: + * type: integer + * example: 123 * 400: - * description: Paramètres invalides + * $ref: '#/components/responses/BadRequest' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/camera/upload', upload.single('image'), ImageController.uploadImage); diff --git a/src/routes/measurementRoutes.js b/src/routes/measurementRoutes.js index 4a3fa53..cd79831 100644 --- a/src/routes/measurementRoutes.js +++ b/src/routes/measurementRoutes.js @@ -7,14 +7,23 @@ const MeasurementController = require('../controllers/measurementController'); * @swagger * /measurements: * get: + * tags: + * - Mesures * summary: Récupère toutes les mesures + * description: Retourne la liste complète des mesures de tous les projets * responses: * 200: * description: Liste de toutes les mesures + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Measurement' * 404: - * description: Aucune mesure trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/measurements', MeasurementController.getAllMeasurements); @@ -22,7 +31,10 @@ router.get('/measurements', MeasurementController.getAllMeasurements); * @swagger * /measurements/{id}: * get: + * tags: + * - Mesures * summary: Récupère une mesure par ID + * description: Retourne les détails d'une mesure spécifique * parameters: * - in: path * name: id @@ -33,12 +45,16 @@ router.get('/measurements', MeasurementController.getAllMeasurements); * responses: * 200: * description: Détails de la mesure + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Measurement' * 400: - * description: ID de mesure invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Mesure non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/measurements/:id', MeasurementController.getMeasurementById); @@ -46,7 +62,10 @@ router.get('/measurements/:id', MeasurementController.getMeasurementById); * @swagger * /measurements/{projectId}/{orderId}: * get: + * tags: + * - Mesures * summary: Récupère une mesure par projet ID et ordre ID + * description: Retourne les détails d'une mesure en fonction du projet et de son numéro d'ordre * parameters: * - in: path * name: projectId @@ -59,16 +78,20 @@ router.get('/measurements/:id', MeasurementController.getMeasurementById); * required: true * schema: * type: integer - * description: ID d'ordre + * description: ID d'ordre séquentiel de la mesure dans le projet * responses: * 200: * description: Détails de la mesure + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Measurement' * 400: - * description: IDs invalides + * $ref: '#/components/responses/BadRequest' * 404: - * description: Mesure non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/measurements/:projectId/:orderId', MeasurementController.getMeasurementByProjectAndOrderId); @@ -76,23 +99,37 @@ router.get('/measurements/:projectId/:orderId', MeasurementController.getMeasure * @swagger * /measurements/{id}: * delete: + * tags: + * - Mesures * summary: Supprime une mesure + * description: Supprime une mesure et l'image associée * parameters: * - in: path * name: id * required: true * schema: * type: integer - * description: ID de la mesure + * description: ID de la mesure à supprimer * responses: * 200: * description: Mesure supprimée avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Mesure supprimée avec succès + * id: + * type: integer + * example: 123 * 400: - * description: ID de mesure invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Mesure non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.delete('/measurements/:id', MeasurementController.deleteMeasurement); diff --git a/src/routes/projectRoutes.js b/src/routes/projectRoutes.js index 58d8faa..b1465a6 100644 --- a/src/routes/projectRoutes.js +++ b/src/routes/projectRoutes.js @@ -7,12 +7,21 @@ const ProjectController = require('../controllers/projectController'); * @swagger * /projects: * get: + * tags: + * - Projets * summary: Récupère tous les projets + * description: Retourne la liste complète des projets de timelapse * responses: * 200: * description: Liste de tous les projets + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Project' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/projects', ProjectController.getAllProjects); @@ -20,7 +29,10 @@ router.get('/projects', ProjectController.getAllProjects); * @swagger * /projects/{id}: * get: + * tags: + * - Projets * summary: Récupère un projet par ID + * description: Retourne les détails d'un projet spécifique * parameters: * - in: path * name: id @@ -31,12 +43,16 @@ router.get('/projects', ProjectController.getAllProjects); * responses: * 200: * description: Détails du projet + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Project' * 400: - * description: ID de projet invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Projet non trouvé + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/projects/:id', ProjectController.getProjectById); @@ -44,7 +60,11 @@ router.get('/projects/:id', ProjectController.getProjectById); * @swagger * /projects/{id}/videos: * get: + * tags: + * - Projets + * - Vidéos * summary: Récupère les vidéos d'un projet + * description: Retourne toutes les vidéos associées à un projet spécifique * parameters: * - in: path * name: id @@ -55,12 +75,18 @@ router.get('/projects/:id', ProjectController.getProjectById); * responses: * 200: * description: Liste des vidéos du projet + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Video' * 400: - * description: ID de projet invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Aucune vidéo trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/projects/:id/videos', ProjectController.getProjectVideos); @@ -68,7 +94,11 @@ router.get('/projects/:id/videos', ProjectController.getProjectVideos); * @swagger * /projects/{id}/measurements: * get: + * tags: + * - Projets + * - Mesures * summary: Récupère les mesures d'un projet + * description: Retourne toutes les mesures associées à un projet spécifique * parameters: * - in: path * name: id @@ -79,12 +109,18 @@ router.get('/projects/:id/videos', ProjectController.getProjectVideos); * responses: * 200: * description: Liste des mesures du projet + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Measurement' * 400: - * description: ID de projet invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Aucune mesure trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/projects/:id/measurements', ProjectController.getProjectMeasurements); @@ -92,7 +128,10 @@ router.get('/projects/:id/measurements', ProjectController.getProjectMeasurement * @swagger * /projects: * post: + * tags: + * - Projets * summary: Crée un nouveau projet + * description: Crée un nouveau projet de timelapse et son répertoire de stockage * requestBody: * required: true * content: @@ -102,18 +141,31 @@ router.get('/projects/:id/measurements', ProjectController.getProjectMeasurement * properties: * name: * type: string + * description: Nom du projet * description: * type: string + * description: Description détaillée du projet * required: * - name * - description * responses: * 201: * description: Projet créé avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Projet ajouté avec succès + * id: + * type: integer + * example: 42 * 400: - * description: Paramètres invalides + * $ref: '#/components/responses/BadRequest' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/projects', ProjectController.createProject); @@ -121,21 +173,35 @@ router.post('/projects', ProjectController.createProject); * @swagger * /projects/{id}: * delete: + * tags: + * - Projets * summary: Supprime un projet + * description: Supprime un projet, toutes ses mesures, images et vidéos associées * parameters: * - in: path * name: id * required: true * schema: * type: integer - * description: ID du projet + * description: ID du projet à supprimer * responses: * 200: * description: Projet supprimé avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Projet supprimé avec succès + * id: + * type: integer + * example: 42 * 400: - * description: ID de projet invalide + * $ref: '#/components/responses/BadRequest' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.delete('/projects/:id', ProjectController.deleteProject); diff --git a/src/routes/videoRoutes.js b/src/routes/videoRoutes.js index 85ebb44..c472787 100644 --- a/src/routes/videoRoutes.js +++ b/src/routes/videoRoutes.js @@ -7,12 +7,21 @@ const VideoController = require('../controllers/videoController'); * @swagger * /videos: * get: + * tags: + * - Vidéos * summary: Récupère toutes les vidéos + * description: Retourne la liste complète des vidéos de tous les projets * responses: * 200: * description: Liste de toutes les vidéos + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/Video' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/videos', VideoController.getAllVideos); @@ -20,7 +29,10 @@ router.get('/videos', VideoController.getAllVideos); * @swagger * /videos/{id}: * get: + * tags: + * - Vidéos * summary: Récupère une vidéo par ID + * description: Retourne les détails d'une vidéo spécifique * parameters: * - in: path * name: id @@ -31,12 +43,16 @@ router.get('/videos', VideoController.getAllVideos); * responses: * 200: * description: Détails de la vidéo + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Video' * 400: - * description: ID de vidéo invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Vidéo non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/videos/:id', VideoController.getVideoById); @@ -44,7 +60,10 @@ router.get('/videos/:id', VideoController.getVideoById); * @swagger * /videos: * post: + * tags: + * - Vidéos * summary: Crée une nouvelle vidéo + * description: Crée une nouvelle vidéo à partir d'une liste de mesures et démarre le processus de rendu * requestBody: * required: true * content: @@ -54,17 +73,21 @@ router.get('/videos/:id', VideoController.getVideoById); * properties: * project_id: * type: integer + * description: ID du projet * measurement_ids: * type: string - * description: JSON array of measurement IDs + * description: Tableau JSON d'IDs de mesures + * example: "[1,2,3,4,5]" * name: * type: string + * description: Nom de la vidéo * resolution: * type: string + * description: Résolution de la vidéo (format LARGEURxHAUTEUR) * example: "1920x1080" * duration: * type: integer - * description: Duration in seconds + * description: Durée souhaitée en secondes * required: * - project_id * - measurement_ids @@ -73,11 +96,22 @@ router.get('/videos/:id', VideoController.getVideoById); * - duration * responses: * 200: - * description: Vidéo créée avec succès + * description: Vidéo créée avec succès et rendu démarré + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Vidéo créée avec succès et le rendu a démarré + * id: + * type: integer + * example: 42 * 400: - * description: Paramètres invalides + * $ref: '#/components/responses/BadRequest' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.post('/videos', VideoController.createVideo); @@ -85,23 +119,34 @@ router.post('/videos', VideoController.createVideo); * @swagger * /videos/{id}: * delete: + * tags: + * - Vidéos * summary: Supprime une vidéo + * description: Supprime une vidéo et le fichier vidéo associé * parameters: * - in: path * name: id * required: true * schema: * type: integer - * description: ID de la vidéo + * description: ID de la vidéo à supprimer * responses: * 200: * description: Vidéo supprimée avec succès + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * example: Vidéo supprimée avec succès * 400: - * description: ID de vidéo invalide + * $ref: '#/components/responses/BadRequest' * 404: - * description: Vidéo non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.delete('/videos/:id', VideoController.deleteVideo); @@ -109,7 +154,10 @@ router.delete('/videos/:id', VideoController.deleteVideo); * @swagger * /videos/file/{video_id}: * get: + * tags: + * - Vidéos * summary: Récupère le fichier vidéo + * description: Télécharge ou diffuse le fichier vidéo avec support du streaming HTTP * parameters: * - in: path * name: video_id @@ -120,14 +168,19 @@ router.delete('/videos/:id', VideoController.deleteVideo); * responses: * 200: * description: Fichier vidéo (stream) + * content: + * video/mp4: + * schema: + * type: string + * format: binary * 206: * description: Fichier vidéo partiel (range request) * 400: - * description: Vidéo pas encore produite + * $ref: '#/components/responses/BadRequest' * 404: - * description: Vidéo non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/videos/file/:video_id', VideoController.getVideoFile); @@ -135,7 +188,10 @@ router.get('/videos/file/:video_id', VideoController.getVideoFile); * @swagger * /videos/progress/{video_id}: * get: + * tags: + * - Vidéos * summary: Récupère la progression du rendu d'une vidéo + * description: Donne des informations sur l'état actuel du rendu d'une vidéo * parameters: * - in: path * name: video_id @@ -153,16 +209,24 @@ router.get('/videos/file/:video_id', VideoController.getVideoFile); * properties: * progress: * type: number + * description: Pourcentage de progression (0-100) + * example: 45.2 * elapsed: * type: number + * description: Temps écoulé depuis le début du rendu (secondes) + * example: 120 * eta: * type: number + * description: Temps estimé restant (secondes) + * example: 150 * status: * type: string + * description: État actuel du rendu + * example: En cours * 404: - * description: Vidéo non trouvée + * $ref: '#/components/responses/NotFound' * 500: - * description: Erreur serveur + * $ref: '#/components/responses/ServerError' */ router.get('/videos/progress/:video_id', VideoController.getVideoProgress);