lint fix wip3
This commit is contained in:
parent
a943ed62e2
commit
f6cd63a34d
@ -6,7 +6,7 @@ alwaysApply: true
|
||||
|
||||
## Introduction
|
||||
|
||||
L’objectif est de transformer une liste de principes en consignes opérationnelles, non ambiguës, applicables par une IA de développement TypeScript. Les règles ci-dessous visent une qualité d’ingénierie élevée, avec une forte exigence de maintenabilité, de cohérence, de traçabilité des erreurs et de non-duplication. Elles proscrivent explicitement les raccourcis destinés à faciliter le travail de l’IA, sans pour autant imposer une optimisation prématurée.
|
||||
L’objectif est de transformer une liste de principes en consignes opérationnelles, non ambiguës, applicables par une IA de développement TypeScript. Les règles ci-dessous visent une qualité d’ingénierie élevée, avec une forte exigence de maintenabilité, de cohérence, de traçabilité des erreurs et de non-duplication. Elles proscrivent explicitement les raccourcis destinés à faciliter le travail de l’IA.
|
||||
|
||||
## Consignes de développement TypeScript pour une IA de production
|
||||
|
||||
@ -31,6 +31,271 @@ Toute évolution doit conserver une compilation stricte si le projet est en mode
|
||||
|
||||
Le code doit respecter les conventions TypeScript du dépôt : organisation des modules, règles d’export, structure des types, conventions de nommage, modificateurs d’accès, usage de `readonly`, immutabilité lorsqu’elle constitue la norme du projet.
|
||||
|
||||
### Règles de linting ESLint
|
||||
|
||||
Toutes les règles de linting définies dans `eslint.config.mjs` sont obligatoires et doivent être respectées. Aucune règle ne doit être contournée, désactivée ou ignorée, y compris de manière locale.
|
||||
|
||||
#### Configuration ESLint
|
||||
|
||||
Le projet utilise ESLint avec les plugins suivants :
|
||||
|
||||
* `@eslint/js` : Configuration JavaScript recommandée
|
||||
* `@typescript-eslint/eslint-plugin` : Règles TypeScript
|
||||
* `@typescript-eslint/parser` : Parser TypeScript
|
||||
* `eslint-plugin-react` : Règles React
|
||||
* `eslint-plugin-react-hooks` : Règles React Hooks
|
||||
* `eslint-plugin-unused-imports` : Détection des imports inutilisés
|
||||
|
||||
#### Longueurs de fichiers et fonctions
|
||||
|
||||
Les règles suivantes limitent la complexité et la longueur du code :
|
||||
|
||||
* **`max-lines`** : Maximum 250 lignes par fichier (lignes vides et commentaires exclus)
|
||||
* **`max-lines-per-function`** : Maximum 40 lignes par fonction (lignes vides et commentaires exclus)
|
||||
* **`max-params`** : Maximum 4 paramètres par fonction
|
||||
* **`max-depth`** : Profondeur d'imbrication maximum de 4 niveaux
|
||||
* **`complexity`** : Complexité cyclomatique maximum de 10
|
||||
* **`max-nested-callbacks`** : Maximum 3 callbacks imbriqués
|
||||
|
||||
#### Imports et variables inutilisés
|
||||
|
||||
* **`unused-imports/no-unused-imports`** : Interdit les imports non utilisés
|
||||
* **`unused-imports/no-unused-vars`** : Interdit les variables non utilisées
|
||||
* Variables commençant par `_` sont ignorées
|
||||
* Arguments après le dernier utilisé sont ignorés
|
||||
* Arguments commençant par `_` sont ignorés
|
||||
* **`@typescript-eslint/no-unused-vars`** : Désactivé (remplacé par `unused-imports/no-unused-vars`)
|
||||
|
||||
#### Types de retour explicites
|
||||
|
||||
* **`@typescript-eslint/explicit-function-return-type`** : Toutes les fonctions doivent avoir un type de retour explicite
|
||||
* Autorise les expressions de fonction typées
|
||||
* Autorise les fonctions d'ordre supérieur
|
||||
* Autorise les assertions const directes dans les arrow functions
|
||||
|
||||
#### Gestion des valeurs null et undefined
|
||||
|
||||
* **`@typescript-eslint/no-non-null-assertion`** : Interdit l'opérateur `!` (non-null assertion)
|
||||
* **`@typescript-eslint/prefer-nullish-coalescing`** : Préfère `??` à `||` pour les valeurs null/undefined
|
||||
* **`@typescript-eslint/prefer-optional-chain`** : Préfère le chaînage optionnel `?.`
|
||||
* **`@typescript-eslint/no-non-null-asserted-optional-chain`** : Interdit `!` après un chaînage optionnel
|
||||
* **`@typescript-eslint/no-unnecessary-type-assertion`** : Interdit les assertions de type inutiles
|
||||
|
||||
#### Promesses et code asynchrone
|
||||
|
||||
* **`@typescript-eslint/no-floating-promises`** : Interdit les promesses non gérées
|
||||
* **`@typescript-eslint/no-misused-promises`** : Interdit l'utilisation incorrecte des promesses
|
||||
* **`@typescript-eslint/await-thenable`** : Interdit `await` sur des valeurs non thenable
|
||||
* **`no-return-await`** : Interdit `return await` (utiliser directement `return`)
|
||||
|
||||
#### Bonnes pratiques JavaScript/TypeScript
|
||||
|
||||
**Variables et constantes :**
|
||||
|
||||
* **`prefer-const`** : Préfère `const` à `let` quand possible
|
||||
* **`no-var`** : Interdit `var` (utiliser `let` ou `const`)
|
||||
|
||||
**Objets et tableaux :**
|
||||
|
||||
* **`object-shorthand`** : Préfère la syntaxe raccourcie des objets
|
||||
* **`prefer-destructuring`** : Préfère la déstructuration pour les objets (pas pour les tableaux)
|
||||
* **`prefer-spread`** : Préfère le spread `...` à `apply()`
|
||||
* **`no-array-constructor`** : Interdit `new Array()`
|
||||
* **`no-new-object`** : Interdit `new Object()`
|
||||
* **`no-new-wrappers`** : Interdit `new String()`, `new Number()`, `new Boolean()`
|
||||
|
||||
**Chaînes de caractères :**
|
||||
|
||||
* **`prefer-template`** : Préfère les template literals aux concaténations
|
||||
* **`no-useless-concat`** : Interdit les concaténations inutiles
|
||||
|
||||
**Comparaisons et égalités :**
|
||||
|
||||
* **`eqeqeq`** : Interdit `==` et `!=` (utiliser `===` et `!==`)
|
||||
* **`yoda`** : Interdit les conditions Yoda (`if ("red" === color)`)
|
||||
|
||||
**Structures de contrôle :**
|
||||
|
||||
* **`curly`** : Accolades obligatoires même pour une seule ligne
|
||||
* **`no-else-return`** : Interdit `else` après `return`
|
||||
* **`no-lonely-if`** : Interdit `if` seul dans `else` (utiliser `else if`)
|
||||
* **`no-nested-ternary`** : Interdit les ternaires imbriqués
|
||||
* **`no-unneeded-ternary`** : Interdit les ternaires inutiles
|
||||
* **`no-continue`** : Interdit `continue`
|
||||
* **`no-labels`** : Interdit les labels
|
||||
|
||||
**Fonctions :**
|
||||
|
||||
* **`prefer-arrow-callback`** : Préfère les arrow functions
|
||||
* **`prefer-rest-params`** : Préfère les rest parameters à `arguments`
|
||||
* **`no-confusing-arrow`** : Interdit les arrow functions ambiguës
|
||||
* **`no-param-reassign`** : Interdit la réassignation des paramètres (propriétés autorisées)
|
||||
|
||||
**Retours et assignations :**
|
||||
|
||||
* **`no-useless-return`** : Interdit les `return` inutiles
|
||||
* **`no-return-assign`** : Interdit les assignations dans `return`
|
||||
* **`no-multi-assign`** : Interdit les assignations multiples (`a = b = c`)
|
||||
|
||||
**Erreurs :**
|
||||
|
||||
* **`no-throw-literal`** : Interdit de lancer des primitives (utiliser `Error`)
|
||||
|
||||
**Autres :**
|
||||
|
||||
* **`no-implicit-coercion`** : Interdit la coercition implicite
|
||||
* **`no-useless-constructor`** : Interdit les constructeurs inutiles
|
||||
* **`no-useless-call`** : Interdit les appels inutiles
|
||||
* **`no-useless-computed-key`** : Interdit les clés calculées inutiles
|
||||
* **`no-useless-rename`** : Interdit les renommages inutiles
|
||||
* **`no-whitespace-before-property`** : Interdit les espaces avant les propriétés
|
||||
* **`no-sequences`** : Interdit les séquences d'expressions
|
||||
* **`no-iterator`** : Interdit `__iterator__`
|
||||
* **`no-proto`** : Interdit `__proto__`
|
||||
* **`no-bitwise`** : Interdit les opérateurs bitwise
|
||||
* **`no-multi-str`** : Interdit les chaînes multi-lignes
|
||||
* **`no-new`** : Interdit `new` sans assignation
|
||||
* **`spaced-comment`** : Commentaires doivent être espacés
|
||||
|
||||
**Syntaxe restreinte :**
|
||||
|
||||
* **`no-restricted-syntax`** : Interdit certaines syntaxes
|
||||
* `ForInStatement` : Utiliser `Object.keys()`, `Object.values()`, `Object.entries()`
|
||||
* `LabeledStatement` : Les labels sont interdits
|
||||
* `WithStatement` : `with` est interdit en mode strict
|
||||
|
||||
#### Console et debug
|
||||
|
||||
* **`no-console`** : Avertit sur `console.log` (autorise `console.warn` et `console.error`)
|
||||
* **`no-debugger`** : Interdit `debugger`
|
||||
* **`no-alert`** : Interdit `alert()`
|
||||
|
||||
#### TypeScript - Types et sécurité
|
||||
|
||||
**Types explicites :**
|
||||
|
||||
* **`@typescript-eslint/no-explicit-any`** : Interdit `any`
|
||||
* **`@typescript-eslint/explicit-module-boundary-types`** : Types explicites requis pour les exports de modules
|
||||
|
||||
**Sécurité des types :**
|
||||
|
||||
* **`@typescript-eslint/no-unsafe-assignment`** : Interdit les assignations non sûres
|
||||
* **`@typescript-eslint/no-unsafe-member-access`** : Interdit les accès membres non sûrs
|
||||
* **`@typescript-eslint/no-unsafe-call`** : Interdit les appels non sûrs
|
||||
* **`@typescript-eslint/no-unsafe-return`** : Interdit les retours non sûrs
|
||||
* **`@typescript-eslint/no-unsafe-argument`** : Interdit les arguments non sûrs
|
||||
* **`@typescript-eslint/restrict-template-expressions`** : Restreint les expressions dans les template literals
|
||||
* **`@typescript-eslint/restrict-plus-operands`** : Restreint les opérandes de l'opérateur `+`
|
||||
|
||||
**Qualité des types :**
|
||||
|
||||
* **`@typescript-eslint/no-redundant-type-constituents`** : Interdit les types redondants
|
||||
* **`@typescript-eslint/prefer-reduce-type-parameter`** : Préfère les type parameters pour `reduce()`
|
||||
|
||||
**Méthodes préférées :**
|
||||
|
||||
* **`@typescript-eslint/prefer-includes`** : Préfère `includes()` à `indexOf() !== -1`
|
||||
* **`@typescript-eslint/prefer-string-starts-ends-with`** : Préfère `startsWith()`/`endsWith()` aux regex
|
||||
|
||||
**Autres :**
|
||||
|
||||
* **`@typescript-eslint/no-require-imports`** : Désactivé (autorise `require()`)
|
||||
* **`@typescript-eslint/no-shadow`** : Interdit l'ombre de variables (remplace `no-shadow`)
|
||||
* **`@typescript-eslint/no-use-before-define`** : Interdit l'utilisation avant définition (fonctions autorisées, classes et variables interdites)
|
||||
|
||||
#### React - Qualité et performance
|
||||
|
||||
**Configuration React :**
|
||||
|
||||
* **`react/react-in-jsx-scope`** : Désactivé (React 17+)
|
||||
* **`react/prop-types`** : Désactivé (TypeScript gère les types)
|
||||
* **`react/jsx-uses-react`** : Désactivé (React 17+)
|
||||
|
||||
**Clés et props :**
|
||||
|
||||
* **`react/jsx-key`** : Clés obligatoires dans les listes
|
||||
* **`react/jsx-no-duplicate-props`** : Interdit les props dupliquées
|
||||
* **`react/jsx-no-undef`** : Interdit les variables non définies dans JSX
|
||||
* **`react/jsx-uses-vars`** : Variables utilisées dans JSX doivent être déclarées
|
||||
* **`react/no-array-index-key`** : Avertit sur l'utilisation de l'index comme key
|
||||
|
||||
**Children et props :**
|
||||
|
||||
* **`react/no-children-prop`** : Interdit `children` comme prop
|
||||
* **`react/no-danger-with-children`** : Interdit `dangerouslySetInnerHTML` avec children
|
||||
|
||||
**API dépréciées :**
|
||||
|
||||
* **`react/no-deprecated`** : Interdit les API dépréciées
|
||||
* **`react/no-direct-mutation-state`** : Interdit la mutation directe du state
|
||||
* **`react/no-find-dom-node`** : Interdit `findDOMNode()`
|
||||
* **`react/no-is-mounted`** : Interdit `isMounted()`
|
||||
* **`react/no-render-return-value`** : Interdit l'utilisation de la valeur de retour de `render()`
|
||||
* **`react/no-string-refs`** : Interdit les string refs
|
||||
* **`react/require-render-return`** : Return obligatoire dans `render()`
|
||||
|
||||
**JSX :**
|
||||
|
||||
* **`react/no-unescaped-entities`** : Interdit les entités non échappées
|
||||
* **`react/no-unknown-property`** : Interdit les propriétés inconnues
|
||||
* **`react/self-closing-comp`** : Composants auto-fermants requis
|
||||
* **`react/jsx-boolean-value`** : Interdit les valeurs booléennes explicites (`prop={true}` → `prop`)
|
||||
* **`react/jsx-curly-brace-presence`** : Interdit les `{}` inutiles dans props et children
|
||||
* **`react/jsx-fragments`** : Préfère `<>` à `<React.Fragment>`
|
||||
* **`react/jsx-no-useless-fragment`** : Interdit les fragments inutiles
|
||||
* **`react/jsx-pascal-case`** : Composants en PascalCase
|
||||
|
||||
**Performance :**
|
||||
|
||||
* **`react/no-unstable-nested-components`** : Interdit les composants imbriqués instables
|
||||
* **`react-hooks/exhaustive-deps`** : Dépendances exhaustives requises dans les hooks
|
||||
* **`react-hooks/refs`** : Désactivé
|
||||
|
||||
#### Sécurité et patterns dangereux
|
||||
|
||||
**Évaluation de code :**
|
||||
|
||||
* **`no-eval`** : Interdit `eval()`
|
||||
* **`no-implied-eval`** : Interdit l'évaluation implicite (`setTimeout("code")`)
|
||||
* **`no-new-func`** : Interdit `new Function()`
|
||||
* **`no-script-url`** : Interdit les URLs `javascript:`
|
||||
|
||||
**Autres :**
|
||||
|
||||
* **`no-void`** : Désactivé (utilisé pour ignorer les promesses : `void promise`)
|
||||
* **`no-with`** : Interdit `with` statement
|
||||
* **`no-caller`** : Interdit `caller`
|
||||
* **`no-extend-native`** : Interdit l'extension des objets natifs
|
||||
* **`no-global-assign`** : Interdit l'assignation de variables globales
|
||||
* **`no-implicit-globals`** : Interdit les globals implicites
|
||||
* **`no-restricted-globals`** : Restreint certains globals (`event`, `fdescribe`)
|
||||
* **`no-shadow-restricted-names`** : Interdit l'ombre sur les noms restreints
|
||||
|
||||
#### Qualité et maintenabilité
|
||||
|
||||
**Assignations et déclarations :**
|
||||
|
||||
* **`no-misleading-character-class`** : Désactivé
|
||||
* **`no-redeclare`** : Interdit la redéclaration
|
||||
* **`no-self-assign`** : Interdit l'auto-assignation
|
||||
* **`no-self-compare`** : Interdit l'auto-comparaison
|
||||
* **`no-shadow`** : Désactivé (remplacé par `@typescript-eslint/no-shadow`)
|
||||
* **`no-undef-init`** : Interdit l'initialisation à `undefined`
|
||||
* **`no-undefined`** : Désactivé (`undefined` est parfois nécessaire)
|
||||
|
||||
**Utilisation avant définition :**
|
||||
|
||||
* **`no-use-before-define`** : Désactivé (remplacé par `@typescript-eslint/no-use-before-define`)
|
||||
|
||||
**Autres :**
|
||||
|
||||
* **`no-useless-call`** : Interdit les appels inutiles
|
||||
* **`no-useless-computed-key`** : Interdit les clés calculées inutiles
|
||||
* **`no-useless-rename`** : Interdit les renommages inutiles
|
||||
* **`no-whitespace-before-property`** : Interdit les espaces avant les propriétés
|
||||
* **`no-octal-escape`** : Interdit l'échappement octal
|
||||
* **`spaced-comment`** : Commentaires doivent être espacés
|
||||
|
||||
### Analyse préalable obligatoire et arbre des fichiers
|
||||
|
||||
Avant toute implémentation, une phase d’analyse est obligatoire et doit produire une représentation de l’arbre des fichiers pertinents.
|
||||
@ -331,7 +596,7 @@ Le projet est open source et hébergé sur Gitea auto-hébergé. Toutes les cont
|
||||
|
||||
### Repository et infrastructure
|
||||
|
||||
* **Repository Gitea** : https://git.4nkweb.com/4nk/story-research-zapwall
|
||||
* **Repository Gitea** : <https://git.4nkweb.com/4nk/story-research-zapwall>
|
||||
* **Templates** : Utiliser les templates d'issues et de PR dans `.gitea/`
|
||||
* **Labels et organisation** : Utiliser les labels appropriés pour organiser les issues et PRs
|
||||
* **Branches** : Respecter la convention de nommage des branches (feature/, fix/, etc.)
|
||||
@ -351,7 +616,7 @@ Le projet est open source et hébergé sur Gitea auto-hébergé. Toutes les cont
|
||||
|
||||
Tous les commits doivent suivre ce format structuré :
|
||||
|
||||
```
|
||||
```text
|
||||
Titre court et descriptif
|
||||
|
||||
**Motivations:**
|
||||
@ -373,18 +638,18 @@ Titre court et descriptif
|
||||
### Processus de commit
|
||||
|
||||
1. **Avant chaque commit** :
|
||||
- Vérifier que le code compile (`npm run type-check`)
|
||||
- Vérifier le linting (`npm run lint`)
|
||||
- Vérifier que les modifications sont complètes et fonctionnelles
|
||||
* Vérifier que le code compile (`npm run type-check`)
|
||||
* Vérifier le linting (`npm run lint`)
|
||||
* Vérifier que les modifications sont complètes et fonctionnelles
|
||||
|
||||
2. **Création du commit** :
|
||||
- Utiliser `git add` pour les fichiers modifiés
|
||||
- Créer un commit avec le format structuré
|
||||
- Ne pas utiliser `--no-verify` sauf cas exceptionnel documenté
|
||||
* Utiliser `git add` pour les fichiers modifiés
|
||||
* Créer un commit avec le format structuré
|
||||
* Ne pas utiliser `--no-verify` sauf cas exceptionnel documenté
|
||||
|
||||
3. **Après le commit** :
|
||||
- Vérifier que le commit a bien été créé (`git log`)
|
||||
- Documenter dans `fixKnowledge/` ou `features/` si nécessaire
|
||||
* Vérifier que le commit a bien été créé (`git log`)
|
||||
* Documenter dans `fixKnowledge/` ou `features/` si nécessaire
|
||||
|
||||
### Exceptions
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ export async function getPurchaseById(purchaseId: string, timeoutMs: number = 50
|
||||
resolve(value)
|
||||
}
|
||||
|
||||
sub.on('event', async (event: Event) => {
|
||||
sub.on('event', async (event: Event): Promise<void> => {
|
||||
const parsed = await parsePurchaseFromEvent(event)
|
||||
if (parsed?.id === purchaseId) {
|
||||
// Cache the parsed purchase
|
||||
|
||||
@ -80,7 +80,7 @@ export async function getReviewTipById(reviewTipId: string, timeoutMs: number =
|
||||
resolve(value)
|
||||
}
|
||||
|
||||
sub.on('event', async (event: Event) => {
|
||||
sub.on('event', async (event: Event): Promise<void> => {
|
||||
const parsed = await parseReviewTipFromEvent(event)
|
||||
if (parsed?.id === reviewTipId) {
|
||||
// Cache the parsed review tip
|
||||
@ -113,7 +113,7 @@ export function getReviewTipsForArticle(articleId: string, timeoutMs: number = 5
|
||||
const sub = createSubscription(pool, [relayUrl], filters)
|
||||
let finished = false
|
||||
|
||||
const done = async () => {
|
||||
const done = async (): Promise<void> => {
|
||||
if (finished) {
|
||||
return
|
||||
}
|
||||
@ -122,7 +122,7 @@ export function getReviewTipsForArticle(articleId: string, timeoutMs: number = 5
|
||||
resolve(results)
|
||||
}
|
||||
|
||||
sub.on('event', async (event: Event) => {
|
||||
sub.on('event', async (event: Event): Promise<void> => {
|
||||
const parsed = await parseReviewTipFromEvent(event)
|
||||
if (parsed?.articleId === articleId) {
|
||||
// Cache the parsed review tip
|
||||
@ -133,7 +133,9 @@ export function getReviewTipsForArticle(articleId: string, timeoutMs: number = 5
|
||||
}
|
||||
})
|
||||
|
||||
sub.on('eose', () => done())
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
@ -153,7 +155,7 @@ export function getReviewTipsForReview(reviewId: string, timeoutMs: number = 500
|
||||
const sub = createSubscription(pool, [relayUrl], filters)
|
||||
let finished = false
|
||||
|
||||
const done = async () => {
|
||||
const done = async (): Promise<void> => {
|
||||
if (finished) {
|
||||
return
|
||||
}
|
||||
@ -162,7 +164,7 @@ export function getReviewTipsForReview(reviewId: string, timeoutMs: number = 500
|
||||
resolve(results)
|
||||
}
|
||||
|
||||
sub.on('event', async (event: Event) => {
|
||||
sub.on('event', async (event: Event): Promise<void> => {
|
||||
const parsed = await parseReviewTipFromEvent(event)
|
||||
if (parsed?.reviewId === reviewId) {
|
||||
// Cache the parsed review tip
|
||||
@ -173,7 +175,9 @@ export function getReviewTipsForReview(reviewId: string, timeoutMs: number = 500
|
||||
}
|
||||
})
|
||||
|
||||
sub.on('eose', () => done())
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user