Skip to content

A powerful Flutter plugin for managing multiple API endpoints with dynamic routing, caching, authentication, and performance-optimized HTTP calls.

License

Notifications You must be signed in to change notification settings

cas8398/api_client_plus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ ApiClientPlus

Pub Version License: MIT Tests wakatime

πŸ”₯ Enterprise-Grade HTTP Client with Blazing Fast Performance

Intelligent caching β€’ Multi-API management β€’ Zero memory leaks

Quick Start β€’ Features β€’ Docs β€’ Examples


🎯 Why ApiClientPlus?

⚑ Blazing Fast

~12ms overhead
225x faster with cache
0 memory leaks

🎨 Developer Friendly

Clean API design
Minimal configuration
Type-safe responses

🏒 Production Ready

Extensive testing
Battle-tested code
Enterprise features


✨ Features

🎯 Core Capabilities

βœ“ Multi-API Configuration    // Manage multiple endpoints seamlessly
βœ“ Intelligent Caching         // 6 strategies with auto-expiration
βœ“ Token Authentication        // Auto-refresh & error handling
βœ“ Request Interceptors        // Transform requests/responses
βœ“ Error Fallback              // Graceful cache fallback
βœ“ Comprehensive Logging       // Debug with precision

πŸ”„ Cache Strategies

Strategy Behavior Best For
🎯 cacheFirst Cache β†’ Network General purpose APIs
🌐 networkFirst Network β†’ Cache Fresh data priority
πŸ’Ύ cacheOnly Cache exclusive Offline-first apps
πŸ”΄ networkOnly No caching Real-time updates
⚑ staleWhileRevalidate Instant + refresh Performance critical
πŸ”„ cacheThenNetwork Cache + background Progressive loading

πŸ“¦ Installation

Add to your pubspec.yaml:

dependencies:
  api_client_plus: ^1.0.0

Install:

flutter pub get

πŸš€ Quick Start

1️⃣ Initialize (One-Time Setup)

import 'package:api_client_plus/api_client_plus.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

   await ApiClientPlus().initialize(
    configs: [
      ApiConfig(
        name: 'dev',
        baseUrl: 'https://api.dev.example.com',
        requiresAuth: true,
      ),
      ApiConfig(
        name: 'api',
        baseUrl: 'https://api.example.com',
        requiresAuth: true,
      ),
      ApiConfig(
        name: 'auth',
        baseUrl: 'https://api.example.com',
        requiresAuth: false,
      ),
    ],
    defaultDomain: kReleaseMode ? 'prod' : 'dev',
    cacheConfig: CacheConfig(
      enableCache: true,
      defaultTtl: Duration(minutes: 10),
    ),
    logConfig: LogConfig(
      showLog: kReleaseMode,
      showCacheLog: false,
      messageLimit: 300,
      prettyJson: false,
      isColored: true,
      showCaller: false,
      logStyle: LogStyle.minimal,
      logLevel: "DEBUG",
    ),
    tokenGetter: () async {
      // final prefs = await SharedPreferences.getInstance();
      // return prefs.getString('access_token');
      return 'my_access_token';
    },
    onTokenInvalid: () async {
      // Redirect logic here
    },
    onRequest: (options) async {
      options.headers['User-Agent'] = 'MyApp/1.0.0';
    },
    onResponse: (response) async {
      debugPrint('βœ… ${response.statusCode} ${response.requestOptions.path}');
    },
    onError: (error) async {
      debugPrint('❌ API Error: ${error.message}');
    },
  );

  runApp(MyApp());
}

2️⃣ Make API Calls

// Simple GET request with caching
final response = await ApiClientService.get(
  '/users',
  useCache: true,
  cacheStrategy: ApiClientCacheStrategy.cacheFirst,
);

// POST with authentication
final user = await ApiClientService.post(
  '/users',
  data: {'name': 'John Doe', 'email': 'john@example.com'},
);

// PUT/PATCH updates
await ApiClientService.put('/users/123', data: updatedData);
await ApiClientService.patch('/users/123', data: partialData);

// DELETE
await ApiClientService.delete('/users/123');

3️⃣ Handle Responses

try {
  final response = await ApiClientService.get('/profile');

  if (response.statusCode == 200) {
    final user = response.data;
    print('Welcome ${user['name']}!');
  }
} on DioException catch (e) {
  if (e.response?.statusCode == 401) {
    // Token expired - auto-refresh triggered
  } else if (e.type == DioExceptionType.connectionError) {
    // Network error - cache fallback available
    final cached = await ApiClientService.get(
      '/profile',
      cacheStrategy: ApiClientCacheStrategy.cacheOnly,
    );
  }
}

🎨 Advanced Usage

πŸ” Multi-API Configuration

Manage different API environments effortlessly:

await ApiClientPlus().initialize(
  configs: [
    ApiConfig(
      name: 'auth',
      baseUrl: 'https://auth.company.com',
      requiresAuth: true,
      connectTimeout: Duration(seconds: 30),
    ),
    ApiConfig(
      name: 'public',
      baseUrl: 'https://api.company.com',
      requiresAuth: false,
      verboseLogging: false,
    ),
    ApiConfig(
      name: 'cdn',
      baseUrl: 'https://cdn.company.com',
      requiresAuth: false,
    ),
  ],
  defaultDomain: 'auth',
);

// Switch between APIs seamlessly
final profile = await ApiClientService.get('/me', domainName: 'auth');
final posts = await ApiClientService.get('/posts', domainName: 'public');
final image = await ApiClientService.get('/avatar.png', domainName: 'cdn');

⚑ Cache Optimization

// Stale-While-Revalidate: Instant response + background refresh
final data = await ApiClientService.get(
  '/dashboard',
  cacheStrategy: ApiClientCacheStrategy.staleWhileRevalidate,
  useCache: true,
  maxStale: Duration(hours: 1),
);

// Cache-Then-Network: Progressive enhancement
final products = await ApiClientService.get(
  '/products',
  cacheStrategy: ApiClientCacheStrategy.cacheThenNetwork,
  onCachedResponse: (cached) {
    // Show cached data immediately
    updateUI(cached.data);
  },
);

πŸ”’ Authentication Flow

await ApiClientPlus().initialize(
  configs: [...],
  tokenGetter: () async {
    // Retrieve token from secure storage
    return await SecureStorage.read('auth_token');
  },
  onTokenInvalid: () async {
    // Handle expired tokens
    await SecureStorage.delete('auth_token');
    Navigator.pushReplacementNamed(context, '/login');
  },
);

🎯 Custom Headers & Options

final response = await ApiClientService.get(
  '/data',
  headers: {
    'X-Custom-Header': 'value',
    'X-Request-ID': uuid.v4(),
  },
  query: {
    'page': 1,
    'limit': 20,
    'sort': 'desc',
  },
  timeout: Duration(seconds: 60),
);

πŸ“Š Performance Benchmarks

Real-World Results

╔═══════════════════════════════════════════════════════════╗
β•‘  Operation              β”‚  Time      β”‚  Rating             β•‘
╠═══════════════════════════════════════════════════════════╣
β•‘  API Call Overhead      β”‚  ~12ms     β”‚  βœ… Excellent       β•‘
β•‘  Route Matching         β”‚  ~600ΞΌs    β”‚  πŸš€ Blazing Fast    β•‘
β•‘  Cache Retrieval        β”‚  ~2ms      β”‚  ⚑ Instant         β•‘
β•‘  Plugin Initialization  β”‚  ~13ms     β”‚  🏎️ Quick           β•‘
β•‘  Memory Leaks           β”‚  0 growth  β”‚  πŸ›‘οΈ Rock Solid      β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Cache Performance Impact

// 🌐 First Request (Network)
πŸ“₯ Response Time: 450ms | Status: 200 | from_cache: false

// ⚑ Second Request (Cache)
πŸ“₯ Response Time: 2ms | Status: 200 | from_cache: true

// πŸŽ‰ Result: 225x FASTER!

Load Testing

βœ“ 100 sequential calls:   1.1 seconds  (11ms avg)
βœ“ 50 domain switches:     549ms        (10.98ms avg)
βœ“ 1000 route matches:     627ms        (0.6ms avg)
βœ“ 10 client instances:    0ms          (instant)
βœ“ 20 configs setup:       1ms          (blazing)

πŸ”§ Configuration Reference

ApiConfig

ApiConfig(
  name: 'myapi',                    // Unique identifier
  baseUrl: 'https://api.example.com',
  connectTimeout: Duration(seconds: 30),
  receiveTimeout: Duration(seconds: 30),
  sendTimeout: Duration(seconds: 30),
  requiresAuth: true,               // Requires token
  verboseLogging: false,            // Detailed logs
  maxRetries: 3,                    // Retry failed requests
  defaultHeaders: {                 // Custom headers
    'Accept': 'application/json',
    'X-App-Version': '1.0.0',
  },
  extra: {'priority': 'high'},      // Custom metadata
)

CacheConfig

CacheConfig(
  enableCache: true,
  defaultTtl: Duration(minutes: 15),
  priority: CachePriority.normal,
  hitCacheOnNetworkFailure: true,   // Fallback on error
  hitCacheOnErrorCodes: [500, 502, 503, 401, 403],
)

LogConfig

LogConfig(
  showLog: true,
  showCacheLog: true,
  logLevel: "DEBUG",                // TRACE, DEBUG, INFO, WARN, ERROR
  prettyJson: true,
  isColored: true,
  messageLimit: 300,
  showTime: true,
  showCaller: false,
  logStyle: LogStyle.minimal,       // minimal, standard, none
)

πŸ› Debugging

Enable Comprehensive Logging

await ApiClientPlus().initialize(
  configs: [...],
  logConfig: LogConfig(
    showLog: true,
    showCacheLog: true,
    logLevel: "DEBUG",
    prettyJson: true,
    isColored: true,
  ),
);

Sample Log Output

INFO πŸ’Ύ Cache Strategy: cache_first for /users
INFO πŸ’Ύ βœ… CACHE HIT: /users (age: 2m 34s)
INFO πŸ“₯ Response: 2ms | 200 | from_cache: true

INFO 🌐 Cache Strategy: network_first for /posts
INFO 🌐 Making network request...
INFO πŸ“₯ Response: 156ms | 200 | from_cache: false
INFO πŸ’Ύ βœ… Cached: /posts (ttl: 10m)

Screenshots

Performance Test Cache Syetem Test


🀝 Contributing

We welcome contributions! Here's how:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ†˜ Support & Resources

πŸ“–
Documentation
πŸ›
Report Bug
πŸ’‘
Request Feature
⭐
Star on GitHub

Built with ❀️ for the Flutter Community

pub.dev β€’ GitHub β€’ Issues

If this package helped you, consider giving it a ⭐ on GitHub!

About

A powerful Flutter plugin for managing multiple API endpoints with dynamic routing, caching, authentication, and performance-optimized HTTP calls.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages