Skip to content

Repository files navigation

api_client

A robust, configurable Flutter package that simplifies HTTP networking by wrapping dio with built-in features for authentication, secure storage management, logging, and error tracking.

Features

  • Global Configuration: Easily configure base URL, headers, and timeouts for all requests.
  • Controller Pattern: Use the BaseController<T> base class to create organized, maintainable API endpoints with built-in response decoding.
  • Flexible Status Codes: Define custom success HTTP status codes per endpoint.
  • Authentication Management: Built-in support for login, logout, and state management via AuthManager.
  • Automatic Token Handling: Interceptors for automatically appending access tokens and handling token refresh workflows.
  • Secure Storage: Integrated flutter_secure_storage to safely store user data, access tokens, and refresh tokens.
  • Third-Party Integrations: Easily add Sentry error tracking (sentry_dio) and advanced logging (awesome_dio_interceptor).

Getting started

Add api_client to your pubspec.yaml dependencies.

dependencies:
api_client: ^0.0.1

Initialize the global configuration before making any requests, typically in your main() method:

import'package:api_client/api_client.dart';
import'package:flutter/material.dart';
voidmain() {
// Set your API Base URLConfiguration.baseUrl ='https://api.example.com/v1';
// Optional flag to enable advanced loggingConfiguration.enableLogs =true;
runApp(constMainApp());
}

Usage

1. Defining an API Controller

Create clear and type-safe endpoints by extending BaseController<T>:

import'package:api_client/api_client.dart';
baseclassGetUsersControllerextendsBaseController<List<User>> {
GetUsersController()
:super(
path:'/users',
method:HTTPMethod.get,
authenticated:true, // Automatically includes auth headers
successStatusCodes:const [200, 201], // Define custom success status codes
responseDecoder: (data) =>
(data asList).map((e) =>User.fromJson(e)).toList(),
);
}

Using the controller

final controller =GetUsersController();

Calling the controller with status result

final result =await controller.callWithResult();
switch (result) {
caseSuccess(data:final data):// Handle successbreak;
caseFailed(error:final error, stackTrace:final stackTrace, data:final data):// Handle errorbreak;
}

Calling the controller without status result

final result =await controller.call();
if(result.isEmpty){
// handle empty result
}else{
// handle result
}

2. Authentication Flow

Use AuthManager to handle login, which automatically extracts and stores the tokens securely.

final authManager =AuthManager.instance;
// Login and save tokensfinal user =await authManager.login(
path:'/auth/login',
data: {
'email':'user@example.com',
'password':'securepassword',
},
decoder: (data) =>UserModel.fromJson(data),
);
// Get current user from secure storagefinal cachedUser =await authManager.me();
// Logout and clear tokensawait authManager.logout(
path:'/auth/logout',
decoder: (data) => data,
);

3. Listening to Authentication Events

You can listen to authManagerStream to respond to session events (like session expiry) across your app:

AuthManager.instance.authManagerStream.listen((event) {
if (event.type ==AuthManagerEventType.sessionExpired) {
// Navigate to Login Screen
}
});

Additional information

For more examples, please refer to the /example folder in the package repository. To contribute or report issues, please check the repository's issue tracker.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages