Fiat

Fiat est un wrapper léger et configurable autour de Dio, conçu pour simplifier les appels API RESTful dans vos projets Flutter et Dart. Il vous permet de gagner du temps en réduisant le code répétitif, en centralisant la gestion des erreurs et en intégrant des retours utilisateurs élégants avec GetX.

💡 Idéal pour les développeurs Flutter qui veulent un client HTTP robuste, réactif, personnalisable et rapide à intégrer.


📦 Pourquoi utiliser Fiat ?

Fonctionnalité Dio seul http (Flutter) Retrofit Chopper Fiat
Gestion centralisée des erreurs ⚠️ partiel ⚠️ partiel ✅ Oui
Résultat standardisé (ApiResult) ✅ Oui
Callbacks de chargement (onLoadingX) ✅ Oui
Mapping JSON typé ❌ manuel ❌ manuel ✅ généré ✅ généré ✅ manuel ou auto
Intégration GetX (snackbar, etc.) ✅ Oui
Cache des requêtes ✅ Oui
Retry automatique ✅ configurable
Logger intégré ⚠️ basique ✅ avec logger
Setup rapide sans code généré ❌ build_runner ❌ build_runner ✅ Oui
Customisation à chaud (timeout, etc.) ⚠️ limité ✅ Oui

🔍 Détails des comparaisons :

  • Dio : Très puissant mais nécessite beaucoup de code pour la gestion d'erreurs, parsing, etc.
  • http : Ultra minimaliste, mais sans support de parsing ni gestion d’erreurs intégrée.
  • Retrofit : Très propre pour les projets à grande échelle, mais lourd à maintenir à cause du build_runner.
  • Chopper : Bonne alternative, mais moins populaire que Retrofit, avec moins de flexibilité sur l’UI/UX.
  • Fiat : Combine la puissance de Dio avec une approche pragmatique : rapide à mettre en place, mais extensible.

🚀 Fonctionnalités principales

  • Gestion centralisée des erreurs HTTP (DioError)
  • Snackbar automatique avec GetX (optionnel)
  • Logs détaillés avec le package logger
  • Résultat typé avec ApiResult.success() et ApiResult.failure()
  • Mappage des erreurs personnalisables (customErrorMessages)
  • Configuration simple : show snackbar, logs, etc.
  • Support Flutter & Dart
  • Facilement testable
  • Support du cache configurable
  • Retry automatique configurable
  • Callbacks onLoadingStart et onLoadingEnd intégrés à toutes les requêtes

🛠️ Installation

Ajoutez cette dépendance dans votre pubspec.yaml :

dependencies:
  Fiat: ^0.0.1+4.4

Et importez-le dans vos fichiers Dart :

import 'package:fiat/fiat.dart';

🎯 Exemple d'utilisation

Initialisation (dans main.dart) :

void main() {
  Fiat.init(FiatConfig(
    baseUrl: 'https://api.example.com',
    debugMode: true,
    showErrorSnackbarByDefault: true,
    defaultHeaders: {'Content-Type': 'application/json'},
    maxRetryAttempts: 3,
    retryPolicy: DefaultRetryPolicy(
      maxAttempts: 3,
      baseDelay: const Duration(seconds: 1),
      exponentialBackoff: true,
    ),
    connectTimeout: const Duration(seconds: 15),
    receiveTimeout: const Duration(seconds: 30),
    tokenGetter: () async => 'your_token_here',
    refreshTokenGetter: () async => 'your_refresh_token_here',
    onTokenUpdated: (newToken) async {
      print('Token mis à jour : $newToken');
    },
    onUnauthorized: () {
      print('Utilisateur non autorisé. Redirection vers la page de connexion.');
    },
    customErrorMessages: {
      404: 'Ressource non trouvée.',
      500: 'Erreur interne du serveur.',
    },
  ));
  runApp(const MyApp());
}

Utilisation de la méthode Get:

Future<void> _getExample() async {
  print('\n=== [GET] /posts/1 ===');

  final result = await Fiat.get<Map<String, dynamic>>(
    '/posts/1',
    fromJson: (data) => data as Map<String, dynamic>,
    onLoadingStart: () => print('GET -> Chargement...'),
    onLoadingEnd: () => print('GET -> Fini !'),
  );

  result.isSuccess ? print('POST -> Succès') : print('POST -> Échec');
  result.isNotFound
      ? print('POST -> Ressource non trouvée')
      : print('POST -> Autre erreur');
  result.isUnauthorized
      ? print('POST -> Non autorisé')
      : print('POST -> Autorisé');
  result.error != null
      ? print('POST -> Erreur: ${result.error}')
      : print('POST -> Pas d\'erreur');
}

Utilisation de la méthode Post:

Future<void> _postExample() async {
  print('\n=== [POST] /posts ===');

  final body = {
    "title": "Hello Fiat",
    "body": "Ceci est un test POST",
    "userId": 1,
  };

  final result = await Fiat.post<User>(
    '/posts',
    data: body,
    fromJson: (data) => User.fromJson(data),
    onLoadingStart: () => print('POST -> Chargement...'),
    onLoadingEnd: () => print('POST -> Fini !'),
  );
  result.isSuccess ? print('POST -> Succès') : print('POST -> Échec');
  result.isNotFound
      ? print('POST -> Ressource non trouvée')
      : print('POST -> Autre erreur');
  result.isUnauthorized
      ? print('POST -> Non autorisé')
      : print('POST -> Autorisé');
  result.error != null
      ? print('POST -> Erreur: ${result.error}')
      : print('POST -> Pas d\'erreur');
}

📥 Gestion du cache & récupération des données stockées

Fiat permet de cacher automatiquement les réponses d'API à différents niveaux de persistance, via le paramètre cacheLevel. Les niveaux disponibles sont :

CacheLevel Description
none (par défaut) Aucune donnée stockée.
memory Données stockées temporairement en mémoire.
storage Données stockées localement via GetStorage (persistantes entre les apps).
memoryThenStorage Vérifie d'abord en mémoire, puis dans le stockage local.

Exemple : Stocker une réponse de connexion

final result = await Fiat.post<LoginResponse>(
  '/auth/login/',
  data: {
    "username": "jn",
    "password": "password1234"
  },
  fromJson: (data) => LoginResponse.fromJson(data),
  cacheLevel: CacheLevel.storage,
  storageKey: 'login_response',
  onLoadingStart: () => print('Connexion...'),
  onLoadingEnd: () => print('Connexion terminée.'),
);

Exemple : Récupérer une donnée stockée

final result = Fiat.getStoredData<LoginResponse>(
  key: 'login_response',
  fromJson: (data) => LoginResponse.fromJson(data),
);

if (result != null) {
  print('Token récupéré depuis le cache : \${result.token}');
} else {
  print('Aucune donnée trouvée en cache.');
}

Exemple avec une liste stockée

final result = Fiat.getStoredData<List<LoginResponse>>(
  key: 'user_list',
  fromJson: (data) {
    if (data is List) {
      return data.map((e) => LoginResponse.fromJson(e)).toList();
    }
    return [];
  },
);

if (result != null && result.isNotEmpty) {
  print('Nombre d\'utilisateurs en cache : \${result.length}');
}

Tu peux maintenant lancer tes requêtes HTTP de manière propre, rapide et centralisée !

Libraries

fiat
Point d’entrée du package Fiat
fiat_client