syrian_dio 0.0.2 copy "syrian_dio: ^0.0.2" to clipboard
syrian_dio: ^0.0.2 copied to clipboard

Production-ready networking layer for Flutter apps built on Dio (Result<T>, error mapping, retry, auth, refresh token).

syrian_dio #

A Flutter networking layer on top of Dio with:

  • Result<T> response model (no exception-based flow in app code)
  • Unified NetworkError mapping
  • Retry interceptor with exponential backoff
  • Automatic auth header injection
  • Optional refresh-token flow
  • Request/response logging

Installation #

dependencies:
  syrian_dio: ^0.0.2

Then:

flutter pub get

Import #

import 'package:syrian_dio/syrian_dio.dart';

Quick Start #

import 'package:syrian_dio/syrian_dio.dart';

final client = DioNetworkClient(
  config: DioConfig(
    baseUrl: 'https://dummyjson.com',
    onUnauthorized: () {
      // Handle forced logout / session expiry.
    },
  ),
  enableRetry: true,
  maxRetries: 3,
  enableLogging: true,
);

Basic GET request #

class User {
  final int id;
  final String firstName;
  final String lastName;

  const User({
    required this.id,
    required this.firstName,
    required this.lastName,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] as int,
      firstName: json['firstName'] as String,
      lastName: json['lastName'] as String,
    );
  }
}

Future<void> loadUser(DioNetworkClient client) async {
  final result = await client.get<User>(
    '/users/1',
    parser: (raw) => User.fromJson(raw as Map<String, dynamic>),
  );

  result.fold(
    (error) => print('Request failed: ${error.type} - ${error.message}'),
    (user) => print('Hello ${user.firstName} ${user.lastName}'),
  );
}

Basic POST request #

Future<void> createUser(DioNetworkClient client) async {
  final result = await client.post<Map<String, dynamic>>(
    '/users/add',
    body: {
      'firstName': 'John',
      'lastName': 'Doe',
    },
    parser: (raw) => raw as Map<String, dynamic>,
  );

  result.fold(
    (error) => print('Create failed: ${error.message}'),
    (data) => print('Created user id: ${data['id']}'),
  );
}

Full Example (Auth + Refresh) #

import 'package:dio/dio.dart';
import 'package:syrian_dio/syrian_dio.dart';

class InMemoryTokenStore implements TokenStore {
  String? _accessToken;
  String? _refreshToken;

  @override
  Future<String?> getAccessToken() async => _accessToken;

  @override
  Future<String?> getRefreshToken() async => _refreshToken;

  @override
  Future<void> saveAccessToken(String token) async {
    _accessToken = token;
  }

  @override
  Future<void> saveRefreshToken(String token) async {
    _refreshToken = token;
  }

  @override
  Future<void> clear() async {
    _accessToken = null;
    _refreshToken = null;
  }
}

Future<DioNetworkClient> buildClient() async {
  final tokenStore = InMemoryTokenStore();
  final refreshDio = Dio(BaseOptions(baseUrl: 'https://api.example.com'));

  return DioNetworkClient(
    config: DioConfig(
      baseUrl: 'https://api.example.com',
      tokenProvider: () => tokenStore.getAccessToken(),
      onUnauthorized: () async {
        await tokenStore.clear();
        print('Session expired. Please log in again.');
      },
    ),
    enableRetry: true,
    maxRetries: 3,
    enableLogging: true,
    logBody: false,
    enableRefreshToken: true,
    tokenStore: tokenStore,
    refreshCall: ({required refreshToken}) async {
      final response = await refreshDio.post(
        '/auth/refresh',
        data: {'refresh_token': refreshToken},
      );

      final data = response.data as Map<String, dynamic>;
      return RefreshResult(
        accessToken: data['access_token'] as String,
        refreshToken: data['refresh_token'] as String?,
      );
    },
  );
}

Future<void> fetchProfile(DioNetworkClient client) async {
  final result = await client.get<Map<String, dynamic>>(
    '/profile',
    parser: (raw) => raw as Map<String, dynamic>,
  );

  result.fold(
    (error) {
      switch (error.type) {
        case NetworkErrorType.noInternet:
          print('No internet connection.');
          break;
        case NetworkErrorType.timeout:
          print('Request timed out.');
          break;
        case NetworkErrorType.unauthorized:
          print('Unauthorized.');
          break;
        default:
          print('Request failed: ${error.message}');
      }
    },
    (profile) => print('Profile loaded: $profile'),
  );
}

Constructor Options #

DioNetworkClient supports:

  • config (DioConfig): base URL, timeouts, token provider, unauthorized callback
  • dio (Dio?): optional custom Dio instance
  • enableLogging / logBody
  • enableRetry / maxRetries
  • enableRefreshToken
  • tokenStore + refreshCall (required when refresh is enabled)
  • onRefreshFailed
  • refreshPathContains
  • extraInterceptors

Error Model #

Possible NetworkErrorType values:

  • noInternet
  • timeout
  • cancelled
  • unauthorized
  • forbidden
  • notFound
  • badResponse
  • server
  • unknown

Run Included Example App #

From repository root:

cd example
flutter pub get
flutter run -d windows

You can also run on Android/Web if those toolchains are configured.

2
likes
0
points
145
downloads

Publisher

unverified uploader

Weekly Downloads

Production-ready networking layer for Flutter apps built on Dio (Result<T>, error mapping, retry, auth, refresh token).

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

dio, flutter, meta

More

Packages that depend on syrian_dio