You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
💡 [REQUEST] - Conventions server-nestjs versionnées dans le dépôt (nommage, tests, sous-fonctions, commentaires)
#2744
Le module apps/server-nestjs a développé, au fil des PRs (ex. #2317), un ensemble de conventions implicites mais cohérentes pour le nommage des fonctions, la structure des tests, les commentaires, et le moment où l'on extrait une sous-fonction. Ces règles ne sont pas documentées de façon centralisée : la structure de module est partiellement couverte par documentation/Modularisation-de-console-server/02-ARCHITECTURE-MODULES.md, mais le reste dépend de la lecture du code existant.
L'objectif est de créer une documentation des conventions versionnée dans le dépôt (sous forme de guide/conventions, chargeable comme skill par les agents travaillant sur server-nestjs), avec exemples réels et pièges, afin que les futures implémentations (et les contributions de l'équipe) les respectent sans avoir à les redécouvrir. Cette documentation doit vivre dans le dépôt, partagée et reviewable comme n'importe quel autre fichier, et non dans un espace personnel.
À compléter (référencer une éventuelle épopée de suivi server-nestjs si existante).
Exemples simples
Conventions observées dans le code actuel, à consigner dans la documentation :
Nommage des fonctions
make* → factory/fixture typée dans *-testing.utils.ts, signature makeX(overrides: Partial<X> = {}): X renvoyant un objet complet avec valeurs par défaut raisonnables (makeProject, makeUser, makeProjectRole, makeSonarqubeProject, makeToUrlParams).
get* → accesseur DB/lecture dans *-queries.utils.ts (reçoit un Prisma.TransactionClient + id) : getProject, getProjectSlug, getProjectContext, getProjectBySlug.
handle* → handler d'event/cron, wrapper fin typé : handleUpsert via @OnEvent (voir plugin.utils.ts + capturePluginResult).
new* → invocation de constructeur dans les useFactory / factories : new Gitlab(...).
Règles de sous-fonction (pattern de plugin.utils.ts)
Extraire une sous-fonction privée quand elle a une forme naturelle propre et doit porter sa propre décorations/trace (ex. syncProject privé avec @StartActiveSpan).
Confiner une assertion de type dans une helper dédiée pour ne pas polluer le reste (ex. keyedBy).
Commentaires fonctionnels « pourquoi » (ex. plugin.utils.ts documente la rationale de capturePluginResult et le confinement de l'assertion de type), pas de commentaires redondants avec le code.
Structure de module
Déjà documentée dans 02-ARCHITECTURE-MODULES.md (slice vertical : module / constants / *-client.service / service / *-datastore.service / utils / *-testing.utils / *.spec.ts). La documentation des conventions doit la référencer, pas la dupliquer.
Spécifications techniques
Créer dans le dépôt une documentation des conventions (fichier versionné et reviewable, ex. apps/server-nestjs/documentation/server-nestjs-conventions.md, ou un skill SKILL.md committé dans le dépôt) contenant :
Les règles de nommage ci-dessus, chaque cas illustré par un extrait réel du repo.
Une section « quand extraire une sous-fonction » (taille, trace dédiée, confinement d'assertion de type, lisibilité).
Une section « structure de test » (colocalisation, mockDeep, factories make*, *.spec.ts par couche).
Une section « commentaires » (pourquoi fonctionnel, pas de bruit).
Une section « structure de module » renvoyant à 02-ARCHITECTURE-MODULES.md.
Section « pièges » : erreurs fréquentes (cast as any, new Date() non déterministe, body: null vs ContractNoBody, littéraux string de nom de plugin/clef de config au lieu de constantes PLUGIN_NAME/*_PLUGIN_KEY).
La documentation doit être committée dans le dépôt (partagée, versionnée, reviewable), et référencée dans les PR de migration en cours.
Description de la solution possible
La solution se décompose en trois niveaux, du plus simple (documentation) au plus automatisé (règles ESLint sur-mesure) :
Niveau 1 — Documentation versionnée et chargeable (cœur de l'issue)
Créer dans le dépôt (ex. apps/server-nestjs/documentation/) un fichier de conventions consommable à la fois par un humain (revue de PR) et par un agent (skill Hermes chargeable, cf. skill hermes-agent). Format recommandé : un SKILL.md committé dans le dépôt, ou un .md référencé par un SKILL.md léger, afin que les sous-agents (delegate_task), Codex/Claude Code, et les futures migrations (#2323 PluginManager) le chargent comme mémoire procédurale versionnée. Le contenu reprend les sections de la « Spécifications techniques » ci-dessus, enrichies d'extraits réels et d'une section « pièges ».
Niveau 2 — Renforcement via la configuration ESLint existante
Le dépôt utilise déjà @antfu/eslint-config centralisé dans packages/eslintconfig. Ajouter des sélecteurs @typescript-eslint/naming-convention ciblant les préfixes du repo :
function / variableLike → camelCase (défaut) ;
factory de test make* → camelCase + prefix: ['make'] (le préfixe est retiré avant la validation du format) ;
accesseur DB get* → prefix: ['get'] ;
handler event/cron handle* → prefix: ['handle'] ;
class / typeLike / interface → PascalCase.
NB : @typescript-eslint/naming-convention est gelé fonctionnellement (plus de nouvelles options) et le mode avec infos de type a un coût de performance ; à activer avec discernement et à mesurer sur le CI.
Niveau 3 — Règles ESLint sur-mesure (ROI le plus élevé)
Les règles natives ne couvrent pas les invariants repo-spécifiques. Implémenter 2–3 règles custom (eslint.org/docs/latest/extend/custom-rules) dans packages/eslintconfig :
interdiction de as any dans server-nestjs (force le typage strict ou un cast localisé + justification) ;
new Date() interdit dans *.spec.ts → exiger faker.date.* pour des tests déterministes ;
(option) get* doit recevoir un Prisma.TransactionClient comme premier paramètre (vérification AST sur *-queries.utils.ts).
Angle workflow agentique
La documentation versionnée sert de « mémoire procédurale » chargeable par les agents ; les règles ESLint ci-dessus sont le professeur déterministe le moins coûteux pour le code généré par LLM (erreur machine-readable, corrigeable en boucle). Pour le déploiement mécanique des conventions (ex. application du nouveau nommage à tous les plugins lors de la dédup #2323), privilégier la délégation parallèle de sous-tâches (subagent-driven-development).
Compatibilité et précédents
La famille de skills nestjs-* (nestjs-build-fixing, nestjs-spec-fixing, nestjs-logging, nestjs-module-migration, nestjs-refactor-safety) est le foyer naturel de ce skill conventions.
Croiser avec writing-plans, test-driven-development, vitest-configuration, simplify-code.
Outils complémentaires déjà présents : tsc --noEmit (strict), secret scanning (gitleaks/aperture), et pour un spike futur les plugins de garde-fou IA (eslint-plugin-ai-guardrails, Factory-AI/eslint-plugin).
Définition du fini
La documentation des conventions (dans le dépôt) documente le nommage des fonctions (make*/get*/build*/handle*/new*) avec exemples réels.
La documentation documente les règles d'extraction de sous-fonction.
La documentation documente la structure de test (*.spec.ts colocalisés, mockDeep, factories).
La documentation documente la convention de commentaires (pourquoi fonctionnel).
La documentation référence la structure de module (02-ARCHITECTURE-MODULES.md) et liste les pièges fréquents.
La documentation est testée sur une PR de migration en cours pour valider son utilité.
This discussion was converted from issue #2324 on September 17, 2026 14:19.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Description
Le module
apps/server-nestjsa développé, au fil des PRs (ex. #2317), un ensemble de conventions implicites mais cohérentes pour le nommage des fonctions, la structure des tests, les commentaires, et le moment où l'on extrait une sous-fonction. Ces règles ne sont pas documentées de façon centralisée : la structure de module est partiellement couverte pardocumentation/Modularisation-de-console-server/02-ARCHITECTURE-MODULES.md, mais le reste dépend de la lecture du code existant.L'objectif est de créer une documentation des conventions versionnée dans le dépôt (sous forme de guide/conventions, chargeable comme skill par les agents travaillant sur
server-nestjs), avec exemples réels et pièges, afin que les futures implémentations (et les contributions de l'équipe) les respectent sans avoir à les redécouvrir. Cette documentation doit vivre dans le dépôt, partagée et reviewable comme n'importe quel autre fichier, et non dans un espace personnel.PRs liées
refactor(server-nestjs): cleanup constants, tests using mockDeep and datastore tighter select: généralisemockDeepet les factories faker (make*), référence de fait pour les conventions de test.PluginManager: la future abstraction des plugins devra respecter ces conventions de nommage/structure.Issues liées
À compléter (référencer une éventuelle épopée de suivi
server-nestjssi existante).Exemples simples
Conventions observées dans le code actuel, à consigner dans la documentation :
Nommage des fonctions
make*→ factory/fixture typée dans*-testing.utils.ts, signaturemakeX(overrides: Partial<X> = {}): Xrenvoyant un objet complet avec valeurs par défaut raisonnables (makeProject,makeUser,makeProjectRole,makeSonarqubeProject,makeToUrlParams).get*→ accesseur DB/lecture dans*-queries.utils.ts(reçoit unPrisma.TransactionClient+ id) :getProject,getProjectSlug,getProjectContext,getProjectBySlug.build*→ transformateur pur / assemblage :buildUpdatedProjectRoles.handle*→ handler d'event/cron, wrapper fin typé :handleUpsertvia@OnEvent(voirplugin.utils.ts+capturePluginResult).new*→ invocation de constructeur dans lesuseFactory/ factories :new Gitlab(...).Règles de sous-fonction (pattern de
plugin.utils.ts)syncProjectprivé avec@StartActiveSpan).keyedBy).Structure de test
*.spec.tscolocalisé à la source ;<module>.service.spec.tspour l'orchestration,-datastore.service.spec.tspour la forme Prisma ; factories centralisées dans*-testing.utils.ts; usage demockDeep(cf. refactor(server-nestjs): cleanup constants, tests using mockDeep and datastore tighter select #2317).Commentaires
plugin.utils.tsdocumente la rationale decapturePluginResultet le confinement de l'assertion de type), pas de commentaires redondants avec le code.Structure de module
02-ARCHITECTURE-MODULES.md(slice vertical :module/constants/*-client.service/service/*-datastore.service/utils/*-testing.utils/*.spec.ts). La documentation des conventions doit la référencer, pas la dupliquer.Spécifications techniques
apps/server-nestjs/documentation/server-nestjs-conventions.md, ou un skillSKILL.mdcommitté dans le dépôt) contenant :mockDeep, factoriesmake*,*.spec.tspar couche).02-ARCHITECTURE-MODULES.md.as any,new Date()non déterministe,body: nullvsContractNoBody, littéraux string de nom de plugin/clef de config au lieu de constantesPLUGIN_NAME/*_PLUGIN_KEY).Description de la solution possible
La solution se décompose en trois niveaux, du plus simple (documentation) au plus automatisé (règles ESLint sur-mesure) :
Niveau 1 — Documentation versionnée et chargeable (cœur de l'issue)
Créer dans le dépôt (ex.
apps/server-nestjs/documentation/) un fichier de conventions consommable à la fois par un humain (revue de PR) et par un agent (skill Hermes chargeable, cf. skillhermes-agent). Format recommandé : unSKILL.mdcommitté dans le dépôt, ou un.mdréférencé par unSKILL.mdléger, afin que les sous-agents (delegate_task), Codex/Claude Code, et les futures migrations (#2323PluginManager) le chargent comme mémoire procédurale versionnée. Le contenu reprend les sections de la « Spécifications techniques » ci-dessus, enrichies d'extraits réels et d'une section « pièges ».Niveau 2 — Renforcement via la configuration ESLint existante
Le dépôt utilise déjà
@antfu/eslint-configcentralisé danspackages/eslintconfig. Ajouter des sélecteurs@typescript-eslint/naming-conventionciblant les préfixes du repo :function/variableLike→camelCase(défaut) ;make*→camelCase+prefix: ['make'](le préfixe est retiré avant la validation du format) ;get*→prefix: ['get'];handle*→prefix: ['handle'];class/typeLike/interface→PascalCase.NB :
@typescript-eslint/naming-conventionest gelé fonctionnellement (plus de nouvelles options) et le mode avec infos de type a un coût de performance ; à activer avec discernement et à mesurer sur le CI.Niveau 3 — Règles ESLint sur-mesure (ROI le plus élevé)
Les règles natives ne couvrent pas les invariants repo-spécifiques. Implémenter 2–3 règles custom (
eslint.org/docs/latest/extend/custom-rules) danspackages/eslintconfig:as anydansserver-nestjs(force le typage strict ou un cast localisé + justification) ;new Date()interdit dans*.spec.ts→ exigerfaker.date.*pour des tests déterministes ;body: nullinterdit → exigerContractNoBody(cf. pièges refactor(server-nestjs): cleanup constants, tests using mockDeep and datastore tighter select #2317) ;get*doit recevoir unPrisma.TransactionClientcomme premier paramètre (vérification AST sur*-queries.utils.ts).Angle workflow agentique
La documentation versionnée sert de « mémoire procédurale » chargeable par les agents ; les règles ESLint ci-dessus sont le professeur déterministe le moins coûteux pour le code généré par LLM (erreur machine-readable, corrigeable en boucle). Pour le déploiement mécanique des conventions (ex. application du nouveau nommage à tous les plugins lors de la dédup
#2323), privilégier la délégation parallèle de sous-tâches (subagent-driven-development).Compatibilité et précédents
nestjs-*(nestjs-build-fixing,nestjs-spec-fixing,nestjs-logging,nestjs-module-migration,nestjs-refactor-safety) est le foyer naturel de ce skill conventions.writing-plans,test-driven-development,vitest-configuration,simplify-code.tsc --noEmit(strict), secret scanning (gitleaks/aperture), et pour un spike futur les plugins de garde-fou IA (eslint-plugin-ai-guardrails,Factory-AI/eslint-plugin).Définition du fini
make*/get*/build*/handle*/new*) avec exemples réels.*.spec.tscolocalisés,mockDeep, factories).02-ARCHITECTURE-MODULES.md) et liste les pièges fréquents.All reactions