lynk_io 0.0.7 copy "lynk_io: ^0.0.7" to clipboard
lynk_io: ^0.0.7 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 for single objects and lists
  • 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
  • .env based 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.7 # latest
  flutter_dotenv: ^5.1.0

🧱 Environment Setup #

To dynamically manage environments like dev, staging, and production:

  1. Create a .env file at the root of your Flutter app:
API_BASE_URL=<your-server-url>
  1. Register the .env file in your pubspec.yaml:
flutter:
  assets:
    - .env
  1. 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 ItemModel {
  final int id;
  final String title;
  final bool completed;

  ItemModel({
    required this.id,
    required this.title,
    required this.completed,
  });

  factory ItemModel.fromJson(Map<String, dynamic> json) => ItemModel(
        id: json['id'],
        title: json['title'],
        completed: json['completed'],
      );
}

Fetch a list of todo items:

final api = locator<ApiClient>();

final result = await api.get<List<ItemModel>>(
  endpoint: '/todos',
  fromJson: (json) {
    final rawList = json as List;
    return rawList.map((e) => ItemModel.fromJson(e)).toList();
  },
);

if (result.isSuccess) {
  final items = result.data!;
  for (final item in items) {
    AppLogger.info('Item: ${item.title}');
  }
} else {
  AppLogger.error('Error: ${result.error!.message}');
}

πŸ“€ POST Request Example #

final result = await api.get<ItemModel>(
  endpoint: '/todos/1',
  fromJson: (json) => ItemModel.fromJson(json as Map<String, dynamic>),
);

πŸ”„ Other Supported Methods #

βœ… GET<T>() #

final result = await api.get<List<ItemModel>>(
  endpoint: '/todos',
  fromJson: (json) {
    final rawList = json as List;
    return rawList.map((e) => ItemModel.fromJson(e)).toList();
  },
);

βœ… POST<T>() #

final result = await api.post<ItemModel>(
  endpoint: '/todos',
  data: {
    'title': 'New task',
    'completed': false,
  },
  fromJson: (json) => ItemModel.fromJson(json as Map<String, dynamic>),
);

βœ… PUT<T>() #

final result = await api.put<ItemModel>(
  endpoint: '/todos/1',
  data: {
    'title': 'Updated task',
    'completed': true,
  },
  fromJson: (json) => ItemModel.fromJson(json as Map<String, dynamic>),
);

βœ… PATCH<T>() #

final result = await api.patch<ItemModel>(
  endpoint: '/todos/1',
  data: {
    'completed': true,
  },
  fromJson: (json) => ItemModel.fromJson(json as Map<String, dynamic>),
);

βœ… DELETE<T>() #

final result = await api.delete<ItemModel>(
  endpoint: '/todos/1',
  fromJson: (json) => ItemModel.fromJson(json as Map<String, dynamic>),
);

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 ApiClient for 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!


6
likes
140
points
5
downloads

Publisher

unverified uploader

Weekly Downloads

A lightweight and modular Flutter networking library for clean API communication using Dio.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

connectivity_plus, dio, flutter, flutter_dotenv, get_it, logger, meta

More

Packages that depend on lynk_io