# Requêtes API
SmartCommon fournit le hook ''useApi'' qui simplifie les appels API avec gestion automatique de l'authentification JWT, du rafraîchissement de token et de la gestion des erreurs.
Documentation [ky](https://github.com/sindresorhus/ky) (client HTTP utilisé)
## Configuration
### 1. Configurer le Provider
Le ''ApiProvider'' doit être configuré dans votre ''LibConfigProvider'' :
```
// src/appConfig.js
export const appConfig = {
debug: true,
api: {
prefixUrl: import.meta.env.VITE_API_URL,
timeout: 30000,
debug: true
}
};
```
```
// src/App.jsx
import { Provider } from '@cap-rel/smartcommon';
import { appConfig } from './appConfig';
export const App = () => {
return (
);
};
```
## Utilisation de useApi
### Importer le hook
```
import { useApi } from '@cap-rel/smartcommon';
```
### Structure retournée
Le hook ''useApi'' retourne un objet avec les méthodes suivantes :
^ Méthode ^ Description ^
| ''user'' | Objet utilisateur connecté (depuis gst) |
| ''login(body, options)'' | Connexion utilisateur, stocke automatiquement les tokens |
| ''logout(options)'' | Déconnexion, supprime les tokens |
| ''entities(options)'' | Récupère les entités disponibles (avant login) |
| ''device(body, options)'' | Enregistre/sélectionne un appareil |
| ''public'' | Instance ky pour les requêtes publiques |
| ''private'' | Instance ky pour les requêtes authentifiées |
| ''get(url, options)'' | Raccourci pour requête GET authentifiée |
| ''post(url, options)'' | Raccourci pour requête POST authentifiée |
| ''put(url, options)'' | Raccourci pour requête PUT authentifiée |
| ''patch(url, options)'' | Raccourci pour requête PATCH authentifiée |
| ''del(url, options)'' | Raccourci pour requête DELETE authentifiée |
### Requête de connexion
```
import { useApi } from '@cap-rel/smartcommon';
import { Input, Button } from '@cap-rel/smartcommon';
export const Login = () => {
const api = useApi();
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const credentials = Object.fromEntries(formData.entries());
try {
const user = await api.login({
...credentials,
rememberMe: true
});
console.log('Connecté:', user);
} catch (error) {
console.error('Erreur de connexion:', error);
}
};
return (
);
};
```
### Requêtes authentifiées
Pour les requêtes nécessitant une authentification, utilisez ''api.private'' :
```
import { useApi } from '@cap-rel/smartcommon';
import { useState, useEffect } from 'react';
import { List, ListItem, Spinner } from '@cap-rel/smartcommon';
export const ItemsList = () => {
const api = useApi();
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchItems = async () => {
try {
const data = await api.private.get('items').json();
setItems(data);
} catch (error) {
console.error('Erreur:', error);
} finally {
setLoading(false);
}
};
fetchItems();
}, []);
if (loading) return ;
return (
{items.map(item => (
{item.name}
))}
);
};
```
### Requêtes POST/PUT/DELETE
```
const api = useApi();
// POST - Créer
const createItem = async (data) => {
return api.private.post('items', { json: data }).json();
};
// PUT - Modifier
const updateItem = async (id, data) => {
return api.private.put(`items/${id}`, { json: data }).json();
};
// DELETE - Supprimer
const deleteItem = async (id) => {
return api.del(`items/${id}`);
};
```
### Méthodes raccourcies
En plus de ''api.private.get(...).json()'', useApi expose des méthodes raccourcies qui gèrent automatiquement la désérialisation JSON et les erreurs :
```
const api = useApi();
// GET
const items = await api.get('items');
// POST avec body JSON
const created = await api.post('items', { json: { label: 'Nouveau' } });
// PUT
const updated = await api.put(`items/${id}`, { json: data });
// PATCH
const patched = await api.patch(`items/${id}`, { json: { status: 1 } });
// DELETE
await api.del(`items/${id}`);
```
#### Option raw (données binaires)
Pour récupérer des données binaires (images, fichiers), passez ''raw: true'' :
```
// Télécharger un fichier en binaire
const response = await api.get(`file/${hash}/binary`, { raw: true });
const blob = await response.blob();
```
#### Option silent (suppression des erreurs)
Par défaut, les erreurs API déclenchent le callback ''onApiError'' (affichage toast). Pour les supprimer :
```
// Ne pas afficher de toast en cas d'erreur
const data = await api.get('optional-endpoint', { silent: true });
```
### Gestion globale des erreurs
Configurez ''onApiError'' dans ''appConfig'' pour centraliser la gestion des erreurs API :
```
// src/appConfig.js
import toast from 'react-hot-toast';
export const appConfig = {
api: {
prefixUrl: import.meta.env.VITE_API_URL,
onApiError: (message) => {
toast.error(message);
},
},
};
```
Quand une requête échoue, useApi :
- Extrait le message d'erreur du body JSON de la réponse (champ ''error'' ou ''message'')
- Appelle ''onApiError'' avec ce message (sauf si ''silent: true'')
- Détecte aussi les erreurs applicatives (HTTP 200 avec champ ''error'' dans le body)
### Accès à l'utilisateur connecté
Le hook ''useApi'' expose directement l'objet utilisateur :
```
const api = useApi();
// Accès direct à l'utilisateur
const user = api.user;
if (user) {
console.log(user.login, user.accessToken);
}
```
### Requêtes publiques
Pour les requêtes ne nécessitant pas d'authentification :
```
const api = useApi();
const fetchPublicData = async () => {
return api.public.get('public/info').json();
};
```
## Fonctionnalités automatiques
### Gestion des tokens
* Le token d'accès est automatiquement ajouté aux headers des requêtes privées
* Le token est rafraîchi automatiquement avant expiration
* En cas d'erreur 401, un refresh est tenté automatiquement
### Circuit breaker
* Protection contre les requêtes en cascade en cas d'erreur serveur
* Blocage temporaire des requêtes après plusieurs échecs
* Détection automatique de la connexion internet
### Headers automatiques
Chaque requête inclut automatiquement :
* ''Authorization: Bearer '' (requêtes privées)
* ''X-DEVICEID: '' (identification de l'appareil)
## Méthode classique (fetch natif)
Si vous préférez utiliser fetch directement (non recommandé) :
Documentation [API Fetch](https://developer.mozilla.org/fr/docs/Web/API/Fetch_API)
```
const API_URL = import.meta.env.VITE_API_URL;
const request = {
method: "POST",
body: JSON.stringify(data),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
}
};
fetch(`${API_URL}/items`, request)
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.error(error));
```
Il est recommandé d'utiliser ''useApi'' plutôt que fetch natif pour bénéficier de la gestion automatique des tokens et du circuit breaker.
## Voir aussi
* [[stockage_de_donnees|Stockage de données]] - Pour persister les données localement
* [[hooks|Hooks]] - Documentation complète des hooks
* [[../back/start|Back (PHP)]] - Configuration des routes API côté serveur