# 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