> For the complete documentation index, see [llms.txt](https://docs.devonyx.fr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.devonyx.fr/getting-started/backend-node-express.md).

# Backend (Node/Express)

### Stack

* **Node.js** (ESM, `"type": "module"`)
* **Express 5**
* **mysql2/promise** pour MySQL
* **jsonwebtoken** pour JWT
* **bcrypt** pour le hash des mots de passe
* **dotenv** pour la config
* **cors** pour le CORS

### Structure des dossiers

```
server/
├── config/
│   └── database.js         # Pool de connexions MySQL
├── controllers/            # Logique métier par entité
│   ├── auth.controller.js
│   ├── parcelles.controller.js
│   ├── cultures.controller.js
│   ├── type_cultures.controller.js
│   ├── meteo.controller.js
│   └── alertes.controller.js
├── middlewares/
│   ├── verifyToken.js      # Vérification JWT
│   └── errorHandler.js     # Gestionnaire d'erreurs global
├── routes/                 # Déclaration des endpoints
│   ├── index.js            # Router racine
│   ├── auth.routes.js
│   ├── parcelles.route.js
│   ├── cultures.route.js
│   ├── observations.route.js
│   ├── meteo.route.js
│   ├── alertes.route.js
│   └── type_cultures.route.js
├── services/
│   └── alertes.service.js  # Moteur de règles
├── src/
│   └── index.js            
├── index.js                # Point d'entrée principal
├── schema.sql              # Copie du schéma BDD
└── package.json

```

> **Note technique :** il existe deux fichiers index.js (racine et src/). Le fichier réellement utilisé en npm run dev est src/index.js, tandis que index.js à la racine contient une version simplifiée. À nettoyer dans une version ultérieure.

### Configuration de la base de données

`config/database.js` crée un **pool de connexion MySQL** avec `mysql2/promise`  :&#x20;

```javascript
const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  port: parseInt(process.env.DB_PORT || '3306'),
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASSWORD || '',
  database: process.env.DB_NAME || 'agriculture_db',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
})
```

Le pool est exporté par défaut et réutilisé dans tous les contrôleurs via `import db from '../config/database.js` ,

### Architecture en couches

<figure><img src="/files/h2a3tV3kQC05MQ0SjP8c" alt=""><figcaption></figcaption></figure>

### Middlewares

#### `errorHandler`

Capture toutes les erreurs propagées via `next(err)` et retourne une réponse JSON cohérente :&#x20;

```javascript
const errorHandler = (err, req, res, next) => {
  console.error(err.stack)
  res.status(err.status || 500).json({
    error: err.message || 'Erreur interne du serveur'
  })
}
```

Toutes les routes utilisent `try/catch + next(err)`  pour propager les erreurs vers ce middleware.

#### `verifyToken`

Vérifie le JWT présent dans le header `Authorization: Baerer <token>`  :&#x20;

```javascript
const verifyToken = (req, res, next) => {
  const header = req.headers.authorization
  if (!header || !header.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Token manquant' })
  }
  const token = header.split(' ')[1]
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET)
    req.user = decoded
    next()
  } catch {
    return res.status(401).json({ error: 'Token invalide ou expiré' })
  }
}
```

### Sécurité

* **Mots de passe :** hashés avec `bcrypt`&#x20;
* **JWT :** signés avec `JWT_SECRET`  (à définir aléatoirement)
* **Requêtes SQL :** 100% paramétrées (pas de concaténation)

### Migration runtime

La table `type_culture` est créée et migrée à chaque démarrage du serveur via une IIFE asynchrone dans `type_cultures.controller.js`

```javascript
;(async () => {
  await db.query(`CREATE TABLE IF NOT EXISTS type_culture (...)`)
  await db.query(`ALTER TABLE culture ADD COLUMN id_type_culture INT NULL`)
    .catch(e => { if (e.errno !== 1060) throw e })
  // + ajout de la contrainte FK
})()
```

Les erreurs MySQL "colonne déjà existante" ou "contrainte déjà existante" sont silencieusement ignorées.

> Cette approche est pratique pour le MVP mais devrait être remplacée par un vrai système de migration (prisma migrate) en production.

### Variables d'environnement requises

| Variable         | Défaut           | Obligatoire | Description                        |
| ---------------- | ---------------- | ----------- | ---------------------------------- |
| `DB_HOST`        | `localhost`      | non         | Host MySQL                         |
| `DB_PORT`        | `3306`           | non         | Port MySQL                         |
| `DB_USER`        | `root`           | non         | Utilisateur MySQL                  |
| `DB_PASSWORD`    | `''`             | non         | Mot de passe MySQL                 |
| `DB_NAME`        | `agriculture_db` | non         | Nom de la base                     |
| `PORT`           | `3000`           | non         | Port du serveur Express            |
| `JWT_SECRET`     | —                | **OUI**     | Clé secrète pour JWT               |
| `JWT_EXPIRES_IN` | —                | **OUI**     | Durée du token (`7d`, `24h`, etc.) |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.devonyx.fr/getting-started/backend-node-express.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
