Last updated:
0 purchases
endpoint core
Endpoint Core #
Endpoint Core is a powerful and flexible Dart package for building and managing API endpoints in Flutter applications. It provides a structured way to define, authenticate, and interact with RESTful APIs, leveraging the popular Dio HTTP client.
Features #
Easy-to-use API endpoint definition
Support for custom data models
Flexible authentication options (Bearer Token, Custom Header)
Built-in request caching with customizable options
Automatic error handling and parsing
Customizable interceptors for logging, connection checking, and more
Dio extension methods for common tasks
Fully testable architecture
Installation #
Add endpoint_core to your pubspec.yaml file:
dependencies:
endpoint_core: ^1.0.0
copied to clipboard
Then run:
flutter pub get
copied to clipboard
Usage #
Defining Custom Models #
First, let's define a custom model that we'll use with our API:
class User {
final int id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
}
copied to clipboard
Defining an API with Custom Models and Cached Endpoints #
Now, let's define an API that uses our custom User model and includes cached endpoints:
import 'package:endpoint_core/endpoint_core.dart';
class UserApi extends Endpoint {
UserApi({
required super.method,
required super.url,
super.validStatusCode,
super.defaultAuthOptions,
super.cacheOptions,
});
@override
String get domainUrl => "https://api.example.com";
static Map<String, ApiEndpoint> endpoints() => {
"getUsers": UserApi(
method: "GET",
url: "/users",
validStatusCode: 200,
defaultAuthOptions: EndpointAuthOptions.bearerToken(
token: "your-token-here",
unauthorizedStatusCodes: [401, 403],
onUnauthorizedCallback: (_) {
// Handle unauthorized access
},
),
cacheOptions: CacheOptions(cacheDuration: Duration(minutes: 5)),
),
"getUserById": UserApi(
method: "GET",
url: "/users/{id}",
validStatusCode: 200,
cacheOptions: CacheOptions(cacheDuration: Duration(hours: 1)),
),
"createUser": UserApi(
method: "POST",
url: "/users",
validStatusCode: 201,
),
"updateUser": UserApi(
method: "PUT",
url: "/users/{id}",
validStatusCode: 200,
),
};
}
copied to clipboard
Making API Calls with Custom Models and Caching #
Here's how you can use the API with custom models and take advantage of caching:
void main() async {
final api = UserApi.endpoints();
// Get all users (cached for 5 minutes)
final users = await api["getUsers"]!.call<List<User>>(
map: (data) => (data as List).map((json) => User.fromJson(json)).toList(),
);
print("All users: $users");
// Get a specific user by ID (cached for 1 hour)
final user = await api["getUserById"]!.call<User>(
pathParameters: {"id": "123"},
map: (data) => User.fromJson(data),
);
print("User with ID 123: $user");
// Create a new user (not cached)
final newUser = await api["createUser"]!.call<User>(
data: User(id: 0, name: "John Doe", email: "[email protected]").toJson(),
map: (data) => User.fromJson(data),
);
print("Newly created user: $newUser");
// Update a user (not cached)
final updatedUser = await api["updateUser"]!.call<User>(
pathParameters: {"id": "123"},
data: {"name": "Jane Doe"},
map: (data) => User.fromJson(data),
);
print("Updated user: $updatedUser");
}
copied to clipboard
Working with Cached Endpoints #
When working with cached endpoints, keep in mind:
The CacheOptions in the endpoint definition determines how long the response will be cached.
Cached responses are automatically returned for subsequent calls within the cache duration.
You can force a fresh request by setting ignoreCache to true:
final freshUserData = await api["getUserById"]!.call<User>(
pathParameters: {"id": "123"},
map: (data) => User.fromJson(data),
ignoreCache: true, // This will ignore any cached data and make a fresh request
);
copied to clipboard
Cache keys are generated based on the full request details, including URL, method, headers, and body. This ensures that different requests don't accidentally share cached data.
The cache is automatically cleared when it expires. You don't need to manually manage cache expiration.
Custom Authentication #
final customAuthOptions = CustomHeaderTokenAuthOptions(
headerName: "X-API-Key",
token: "your-api-key-here",
unauthorizedStatusCodes: [401],
onUnauthorizedCallback: (_) {
// Handle unauthorized access
},
);
final result = await api["someEndpoint"]!.call(
authOptions: customAuthOptions,
// other parameters...
);
copied to clipboard
Using Interceptors #
The package comes with several built-in interceptors:
AuthInterceptor: Handles authentication
CacheInterceptor: Manages request caching
ConnectionChecker: Checks for internet connectivity
RequestLogger: Logs request and response details
You can add custom interceptors when defining your API:
class MyApi extends Endpoint {
MyApi({
// ... other parameters
}) : super(
interceptors: [MyCustomInterceptor()],
);
// ... rest of the class
}
copied to clipboard
Custom Caching Behavior #
If you need more control over caching behavior, you can implement a custom CacheInterceptor:
class CustomCacheInterceptor extends CacheInterceptor {
CustomCacheInterceptor({required super.validStatusCode});
@override
Future<void> onResponse(Response response, ResponseInterceptorHandler handler) async {
// Custom caching logic here
// For example, you might want to cache based on custom headers:
final customCacheDuration = response.headers.value('X-Cache-Duration');
if (customCacheDuration != null) {
final duration = Duration(seconds: int.parse(customCacheDuration));
// Implement custom caching logic with this duration
}
super.onResponse(response, handler);
}
}
// Then use this custom interceptor when defining your API:
class UserApi extends Endpoint {
UserApi({
// ... other parameters
}) : super(
interceptors: [CustomCacheInterceptor(validStatusCode: 200)],
);
// ... rest of the class
}
copied to clipboard
Dio Extensions #
The package provides useful Dio extensions:
final dio = Dio();
// Add authorization header to all requests
dio.addAuthorizationInterceptor('your-token-here');
// Add a custom header to all requests
dio.addCustomHeader('X-Custom-Header', 'custom-value');
// Check if a response is successful
if (response.isSuccessful) {
// Handle successful response
}
// Get a user-friendly error message
print(dioError.friendlyMessage);
copied to clipboard
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.