lynk_io 0.0.5
lynk_io: ^0.0.5 copied to clipboard
A lightweight and modular Flutter networking library for clean API communication using Dio.
๐ lynk_io #
A scalable and reusable API communication layer built with Dio for Flutter apps.
Designed to simplify API calls, error handling, and dependency setup โ following Clean Architecture, modular design, and SOLID principles.
๐ Features #
- Generic GET, POST, PUT, PATCH, DELETE support
- Clean separation of concerns using SOLID principles
- Global error handling with structured exceptions
- Built-in pluggable logger
- Plug-and-play dependency injection via
get_it .envbased API URL configuration (cross-platform)- Optional auth interceptor via
getToken()callback - Multipart file upload / download utilities
- Easily extensible and testable structure
๐ฆ Installation #
Add this to your pubspec.yaml:
dependencies:
lynk_io: ^0.0.5 # latest
flutter_dotenv: ^5.1.0
๐งฑ Environment Setup #
To dynamically manage environments like dev, staging, and production:
- Create a
.envfile at the root of your Flutter app:
API_BASE_URL=<your-server-url>
- Register the
.envfile in yourpubspec.yaml:
flutter:
assets:
- .env
- Load the environment and set up dependencies before
runApp():
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:lynk_io/lynk_io.dart';
void main() async {
await dotenv.load();
final baseUrl = dotenv.env['API_BASE_URL'] ?? '';
setupDependencies(
baseUrl: baseUrl,
getToken: () async {
// Replace with your token logic
return 'your-auth-token';
},
);
runApp(MyApp());
}
๐ก๏ธ Token-based Auth Interceptor #
The package supports authenticated requests via an optional getToken() function:
setupDependencies(
baseUrl: baseUrl,
getToken: () async {
// fetch your token securely
return await storage.read(key: 'accessToken');
},
);
All requests will automatically include:
Authorization: Bearer <your-token>
๐ฆ Example API Usage #
Define a model class:
class User {
final int id;
final String name;
User({required this.id, required this.name});
factory User.fromJson(Map<String, dynamic> json) =>
User(id: json['id'], name: json['name']);
}
Fetch user data:
final api = locator<ApiClient>();
final result = await api.get<User>(
endpoint: '/user/<user-id>',
fromJson: User.fromJson,
);
if (result.isSuccess) {
AppLogger.log("User: ${result.data!.name}");
} else {
AppLogger.error("Error: ${result.error!.message}");
}
๐ค POST Request Example #
final result = await api.post<User>(
endpoint: '/users',
body: {
'name': 'Siva G',
'email': 'siva@example.com',
},
fromJson: User.fromJson,
);
๐ Other Supported Methods #
โ
GET<T>() #
api.get<T>(
endpoint: '/items',
fromJson: T.fromJson,
);
โ
POST<T>() #
api.post<T>(
endpoint: '/items',
body: {...},
fromJson: T.fromJson,
);
โ
PUT<T>() #
api.put<T>(
endpoint: '/items/1',
body: {...},
fromJson: T.fromJson,
);
โ
PATCH<T>() #
api.patch<T>(
endpoint: '/items/1',
body: {...},
fromJson: T.fromJson,
);
โ
DELETE<T>() #
api.delete<T>(
endpoint: '/items/1',
fromJson: T.fromJson,
);
All methods return a unified ApiResponse<T> that encapsulates success and error data.
๐ File Upload & Download #
Upload a file:
final api = locator<ApiClient>();
await api.files.uploadFile(
'path/to/file.jpg',
'/upload-endpoint',
);
Download a file:
await api.files.downloadFile(
'https://server.com/file.pdf',
'/local/save/path/file.pdf',
);
๐งช Testing & Extensibility #
- Easily mock the
ApiClientfor tests - Pass custom interceptors via
setupDependencies(...) - Add more interceptors like caching, logging, etc.
๐จโ๐ป Author #
Built and maintained with โค๏ธ by Siva G
Feel free to contribute, fork, or drop feedback!