Skip to content

Commit e976965

Browse files
committed
feat: Add detailed JSDoc comments to AppController and AppService for improved documentation
1 parent 67acf2a commit e976965

File tree

2 files changed

+209
-40
lines changed

2 files changed

+209
-40
lines changed

apps/api/src/app.controller.ts

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,54 @@ import { AbstractController } from '~/_common/abstracts/abstract.controller';
55
import { Public } from './_common/decorators/public.decorator';
66
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiResponse } from '@nestjs/swagger';
77

8+
/**
9+
* Contrôleur principal de l'application.
10+
*
11+
* Ce contrôleur expose les endpoints racine de l'API, incluant les informations
12+
* sur l'application, la vérification des mises à jour et les utilitaires de debug.
13+
*
14+
* @class AppController
15+
* @extends {AbstractController}
16+
*
17+
* @description
18+
* Endpoints disponibles :
19+
* - GET / - Informations sur l'API (version, nom, etc.)
20+
* - GET /get-update/:project - Vérification des mises à jour disponibles
21+
* - GET /debug-sentry - Endpoint de test pour Sentry (erreur forcée)
22+
*/
823
@Public()
924
@Controller()
1025
@ApiBearerAuth()
1126
// @see https://stackoverflow.com/questions/67314808/how-to-disable-security-for-a-specific-controller-method-in-nestjs-swagger
1227
export class AppController extends AbstractController {
28+
/**
29+
* Constructeur du contrôleur AppController.
30+
*
31+
* @param {AppService} appService - Service principal de l'application
32+
*/
1333
constructor(private readonly appService: AppService) {
1434
super();
1535
}
1636

1737
/**
18-
* This endpoint returns the API information.
19-
* It retrieves the package information from the AppService and returns it in the response.
38+
* Récupère les informations de l'API.
39+
*
40+
* Retourne les métadonnées de l'application telles que le nom,
41+
* la version, la description, etc. provenant du package.json.
42+
*
43+
* @param {Response} res - Objet de réponse Express
44+
* @returns {Response} Informations de l'API au format JSON
45+
*
46+
* @example
47+
* ```typescript
48+
* // GET /
49+
* {
50+
* name: "sesame-orchestrator",
51+
* version: "1.2.3",
52+
* description: "Orchestrateur Sesame",
53+
* ...
54+
* }
55+
* ```
2056
*/
2157
@Get()
2258
@ApiOperation({ summary: 'Get API infos' })
@@ -28,13 +64,42 @@ export class AppController extends AbstractController {
2864
}
2965

3066
/**
31-
* This endpoint checks for updates of the specified project.
32-
* It compares the current version with the latest version available on GitHub.
33-
* If the project is not the same as the package name or if a current version is provided,
34-
* it validates the current version format.
35-
* If the current version is not in the format X.Y.Z, it throws a BadRequestException.
36-
* It returns the project name, whether an update is available, the current version,
37-
* and the last version available.
67+
* Vérifie les mises à jour disponibles pour un projet.
68+
*
69+
* Compare la version actuelle du projet avec la dernière version disponible
70+
* sur GitHub et indique si une mise à jour est disponible.
71+
*
72+
* @param {Response} res - Objet de réponse Express
73+
* @param {ProjectsList} [project] - Nom du projet à vérifier
74+
* @param {string} [current] - Version actuelle du projet (optionnel, format X.Y.Z)
75+
* @returns {Promise<Response>} Informations sur les mises à jour disponibles
76+
* @throws {BadRequestException} Si le paramètre current n'est pas au format X.Y.Z
77+
*
78+
* @description
79+
* Processus de vérification :
80+
* 1. Récupère la version actuelle (paramètre ou version du package)
81+
* 2. Valide le format de version si fourni (doit être X.Y.Z)
82+
* 3. Interroge l'API GitHub pour récupérer la dernière release
83+
* 4. Compare les versions (majeur, mineur, patch)
84+
* 5. Retourne le résultat avec indication de mise à jour disponible
85+
*
86+
* Projets supportés :
87+
* - sesame-orchestrator
88+
* - sesame-daemon
89+
* - sesame-app-manager
90+
*
91+
* @example
92+
* ```typescript
93+
* // GET /get-update/sesame-orchestrator?current=1.2.3
94+
* {
95+
* data: {
96+
* project: "sesame-orchestrator",
97+
* updateAvailable: true,
98+
* currentVersion: "1.2.3",
99+
* lastVersion: "1.3.0"
100+
* }
101+
* }
102+
* ```
38103
*/
39104
@ApiQuery({ name: 'current', required: false })
40105
@Get('/get-update/:project(sesame-orchestrator|sesame-daemon|sesame-app-manager)')
@@ -47,13 +112,7 @@ export class AppController extends AbstractController {
47112
const currentVersion = current || pkgInfo.version;
48113
const [lastMajor, lastMinor, lastPatch] = currentVersion.split('.').map(Number);
49114

50-
/**
51-
* If the project is not the same as the package name or if a current version is provided,
52-
* we validate the current version format.
53-
* If the current version is not in the format X.Y.Z, we throw a BadRequestException.
54-
*
55-
* This ensures that the current version is always in a valid format before proceeding with the comparison.
56-
*/
115+
// Validation du format de version si le projet est différent ou si une version est fournie
57116
if (project !== pkgInfo.name || current) {
58117
if (!/[0-9]+\.[0-9]+\.[0-9]+/.test(current)) {
59118
throw new BadRequestException('Invalid version for current parameter');
@@ -80,6 +139,20 @@ export class AppController extends AbstractController {
80139
});
81140
}
82141

142+
/**
143+
* Endpoint de debug pour tester l'intégration Sentry.
144+
*
145+
* Génère volontairement une erreur pour vérifier que les erreurs
146+
* sont correctement capturées et envoyées à Sentry.
147+
*
148+
* @throws {Error} Erreur de test Sentry
149+
*
150+
* @example
151+
* ```typescript
152+
* // GET /debug-sentry
153+
* // Lance une erreur "My first Sentry error!"
154+
* ```
155+
*/
83156
@Get("/debug-sentry")
84157
getError() {
85158
throw new Error("My first Sentry error!");

apps/api/src/app.service.ts

Lines changed: 120 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,22 @@ import { getLogLevel } from './_common/functions/get-log-level';
1212
import { ConfigService } from '@nestjs/config';
1313
import { isConsoleEntrypoint } from './_common/functions/is-cli';
1414

15+
/**
16+
* Énumération des projets Sesame disponibles pour la vérification de mises à jour.
17+
* @enum {string}
18+
*/
1519
export enum ProjectsList {
20+
/** Orchestrateur Sesame */
1621
SESAME_ORCHESTRATOR = 'sesame-orchestrator',
22+
/** Daemon Sesame */
1723
SESAME_DAEMON = 'sesame-daemon',
24+
/** Gestionnaire d'applications Sesame */
1825
SESAME_APP_MANAGER = 'sesame-app-manager',
1926
}
2027

28+
/**
29+
* Interface représentant un auteur GitHub.
30+
*/
2131
export interface GithubAuthor {
2232
login: string;
2333
id: number;
@@ -40,10 +50,16 @@ export interface GithubAuthor {
4050
site_admin: boolean;
4151
}
4252

53+
/**
54+
* Interface représentant un asset GitHub d'une release.
55+
*/
4356
export interface GithubAsset {
4457
[key: string]: any;
4558
}
4659

60+
/**
61+
* Interface représentant une release GitHub.
62+
*/
4763
export interface GithubUpdate {
4864
url: string;
4965
assets_url: string;
@@ -65,15 +81,57 @@ export interface GithubUpdate {
6581
body: string;
6682
}
6783

84+
/**
85+
* Service principal de l'application.
86+
*
87+
* Ce service gère les fonctionnalités globales de l'application, notamment
88+
* la récupération des informations de version et la vérification des mises à jour
89+
* disponibles pour les différents projets Sesame via l'API GitHub.
90+
*
91+
* @class AppService
92+
* @extends {AbstractService}
93+
* @implements {OnApplicationBootstrap}
94+
*
95+
* @description
96+
* Fonctionnalités principales :
97+
* - Récupération des informations du package (nom, version)
98+
* - Vérification périodique des mises à jour via l'API GitHub
99+
* - Cache LRU des releases GitHub (TTL 6 heures)
100+
* - Tâche planifiée toutes les 6 heures pour actualiser les informations
101+
* - Configuration du niveau de log en mode console
102+
*
103+
* Le service utilise un cache pour limiter les appels à l'API GitHub et améliorer
104+
* les performances. Les données sont automatiquement rafraîchies toutes les 6 heures.
105+
*/
68106
@Injectable()
69107
export class AppService extends AbstractService implements OnApplicationBootstrap {
108+
/**
109+
* Cache LRU pour stocker les informations de releases GitHub.
110+
* TTL de 6 heures avec purge automatique.
111+
*
112+
* @protected
113+
* @type {LRUCache}
114+
*/
70115
protected storage = new LRUCache({
71-
ttl: 1_000 * 60 * 60 * 6, // 6 hours
116+
ttl: 1_000 * 60 * 60 * 6, // 6 heures
72117
ttlAutopurge: true,
73118
});
74119

120+
/**
121+
* Informations du package.json de l'application.
122+
*
123+
* @protected
124+
* @type {Partial<PackageJson>}
125+
*/
75126
protected package: Partial<PackageJson>;
76127

128+
/**
129+
* Constructeur du service AppService.
130+
*
131+
* @param {ModuleRef} moduleRef - Référence au module NestJS
132+
* @param {HttpService} httpService - Service HTTP pour les appels à l'API GitHub
133+
* @param {ConfigService} config - Service de configuration
134+
*/
77135
public constructor(
78136
protected moduleRef: ModuleRef,
79137
private readonly httpService: HttpService,
@@ -84,12 +142,13 @@ export class AppService extends AbstractService implements OnApplicationBootstra
84142
}
85143

86144
/**
87-
* On application bootstrap, this method is called to initialize the service.
88-
* It logs the start of the bootstrap process and fetches the latest releases for each project
89-
* in the ProjectsList enum.
90-
* It uses the fetchGithubRelease method to get the latest releases from GitHub.
145+
* Hook appelé au démarrage de l'application.
146+
*
147+
* Initialise le service en récupérant les dernières releases pour chaque projet
148+
* Sesame disponible. Configure également le niveau de log approprié en mode console.
91149
*
92-
* @returns {Promise<void>} A promise that resolves when the bootstrap process is complete.
150+
* @async
151+
* @returns {Promise<void>}
93152
*/
94153
public async onApplicationBootstrap(): Promise<void> {
95154
this.logger.debug('Application service bootstrap starting...');
@@ -106,22 +165,29 @@ export class AppService extends AbstractService implements OnApplicationBootstra
106165
this.logger.log('Application service bootstrap completed.');
107166

108167
if (isConsoleEntrypoint) {
109-
// Reactive logger with appropriate log level in console mode !
168+
// Réactive le logger avec le niveau de log approprié en mode console
110169
this.logger.localInstance.setLogLevels(
111170
getLogLevel(this.config.get('application.logLevel', 'debug'))
112171
);
113172
}
114173
}
115174

116175
/**
117-
* Cron job to fetch the latest releases of projects every 6 hours.
118-
* This method logs the start and end of the job, and fetches updates for each project in the ProjectsList.
119-
* It uses the fetchGithubRelease method to get the latest releases from GitHub.
120-
* The job is scheduled using the CronExpression.EVERY_6_HOURS expression.
176+
* Tâche planifiée pour rafraîchir les releases toutes les 6 heures.
177+
*
178+
* Récupère automatiquement les dernières versions disponibles pour chaque projet
179+
* depuis GitHub. Ignorée en mode développement et en mode console.
121180
*
122-
* @Cron(CronExpression.EVERY_6_HOURS)
181+
* @async
123182
* @returns {Promise<void>}
124-
* @memberof AppService
183+
*
184+
* @description
185+
* Planification : Toutes les 6 heures via @Cron
186+
*
187+
* Comportement :
188+
* - Mode console : Skip l'exécution
189+
* - Mode développement : Skip la récupération des releases
190+
* - Mode production : Récupère les releases pour tous les projets
125191
*/
126192
@Cron(CronExpression.EVERY_6_HOURS)
127193
public async handleCron(): Promise<void> {
@@ -145,19 +211,35 @@ export class AppService extends AbstractService implements OnApplicationBootstra
145211
}
146212

147213
/**
148-
* Returns basic information about the application, such as name and version.
214+
* Retourne les informations de base de l'application.
215+
*
216+
* Extrait le nom et la version depuis le package.json.
149217
*
150-
* @returns {Partial<PackageJson>} Returns basic information about the application, such as name and version.
218+
* @returns {Partial<PackageJson>} Informations de l'application (nom, version)
219+
*
220+
* @example
221+
* ```typescript
222+
* const info = appService.getInfo();
223+
* // { name: "sesame-orchestrator", version: "1.2.3" }
224+
* ```
151225
*/
152226
public getInfo(): Partial<PackageJson> {
153227
return pick(this.package, ['name', 'version']);
154228
}
155229

156230
/**
157-
* Fetches the latest release information for a specified project from GitHub.
231+
* Récupère les informations de mise à jour pour un projet depuis le cache.
232+
*
233+
* Retourne les informations de la dernière release GitHub si elles sont
234+
* présentes dans le cache, sinon retourne null.
235+
*
236+
* @param {ProjectsList} project - Nom du projet
237+
* @returns {GithubUpdate | null} Informations de la dernière release ou null
238+
* @throws {BadRequestException} Si le nom du projet est invalide
158239
*
159-
* @param project The project name to fetch updates for.
160-
* @returns {Promise<GithubUpdate>} A promise that resolves to the latest release information for the specified project.
240+
* @description
241+
* Cette méthode ne fait pas d'appel à l'API GitHub, elle consulte uniquement
242+
* le cache. Les données sont mises en cache par fetchGithubRelease().
161243
*/
162244
public getProjectUpdate(project: ProjectsList): GithubUpdate {
163245
if (!Object.values(ProjectsList).includes(project)) {
@@ -170,14 +252,28 @@ export class AppService extends AbstractService implements OnApplicationBootstra
170252
return this.storage.get(project) as GithubUpdate;
171253
}
172254

173-
return null; // Return null if the project is not cached
255+
return null; // Retourne null si le projet n'est pas en cache
174256
}
175257

176258
/**
177-
* Fetches the latest release information for a specified project from GitHub.
259+
* Récupère les informations de la dernière release depuis l'API GitHub.
260+
*
261+
* Interroge l'API GitHub pour obtenir la dernière release d'un projet,
262+
* met en cache le résultat et implémente une logique de retry en cas d'erreur.
263+
*
264+
* @private
265+
* @async
266+
* @param {ProjectsList} project - Nom du projet
267+
* @param {number} [retry=0] - Nombre de tentatives effectuées
268+
* @returns {Promise<GithubUpdate | null>} Informations de la release ou null en cas d'échec
178269
*
179-
* @param project The project name to fetch updates for.
180-
* @returns {Promise<GithubUpdate>} A promise that resolves to the latest release information for the specified project.
270+
* @description
271+
* Processus de récupération :
272+
* 1. Vérifie si les données sont déjà en cache
273+
* 2. Si non, interroge l'API GitHub
274+
* 3. Met en cache le résultat (TTL 6 heures)
275+
* 4. En cas d'erreur, retry jusqu'à 3 fois avec délai de 60 secondes
276+
* 5. Après 3 échecs, log une erreur fatale et retourne null
181277
*/
182278
private async fetchGithubRelease(project: ProjectsList, retry = 0): Promise<any> {
183279
if (this.storage.has(project)) {
@@ -203,13 +299,13 @@ export class AppService extends AbstractService implements OnApplicationBootstra
203299
if (retry >= 3) {
204300
this.logger.fatal(`Failed to fetch release for ${project} after multiple retries: ${error.message}`);
205301

206-
return null; // Return null or handle as needed
302+
return null; // Retourne null après 3 tentatives échouées
207303
}
208304

209305
setTimeout(() => {
210306
this.logger.verbose(`Retrying to fetch ${project} release after error: ${error.message}`);
211307
return this.fetchGithubRelease(project, retry + 1);
212-
}, 1_000 * 60); // Retry after 60 seconds
308+
}, 1_000 * 60); // Retry après 60 secondes
213309
}
214310
}
215311
}

0 commit comments

Comments
 (0)