networking_layer 1.0.0 copy "networking_layer: ^1.0.0" to clipboard
networking_layer: ^1.0.0 copied to clipboard

A robust, solid-compliant networking layer using Dio.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:dartz/dartz.dart' hide State;
import 'package:networking_layer/networking_layer.dart';

// -----------------------------------------------------------------------------
// 1. Data Models
// -----------------------------------------------------------------------------
class User {
  final int id;
  final String name;
  final String? email;

  User({required this.id, required this.name, this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'] is int
          ? json['id']
          : int.tryParse(json['id'].toString()) ?? 0,
      name: json['name'] ?? '',
      email: json['email'],
    );
  }

  Map<String, dynamic> toJson() => {'name': name, 'email': email};
}

// -----------------------------------------------------------------------------
// 2. Repository with ApiClient Mixin
// -----------------------------------------------------------------------------
class UserRepository with ApiClient {
  // ----------------- REST EXAMPLES -----------------

  /// [REST] GET Request
  Future<Either<HelperResponse, User>> getUserREST(String id) async {
    return await get<User>(
      '/users/$id',
      fromJson: (json) => User.fromJson(json),
    );
  }

  /// [REST] POST Request (Create User)
  Future<Either<HelperResponse, User>> createUserREST(User user) async {
    return await post<User>(
      '/users',
      data: user.toJson(),
      fromJson: (json) => User.fromJson(json),
    );
  }

  // ----------------- GRAPHQL EXAMPLES -----------------

  /// [GraphQL] Query Example
  /// Note: JSONPlaceholder doesn't support GraphQL, so this URL will likely fail
  /// with 404 if run against it, but the code structure is correct.
  Future<Either<HelperResponse, User>> getUserGraphQL(String id) async {
    const String query = r'''
      query GetUser($id: ID!) {
        user(id: $id) {
          id
          name
          email
        }
      }
    ''';

    return await graphQLQuery<User>(
      query,
      variables: {'id': id},
      dataKey: 'user', // content inside data: { user: { ... } }
      fromJson: (json) => User.fromJson(json),
    );
  }

  /// [GraphQL] Mutation Example
  Future<Either<HelperResponse, User>> updateUserGraphQL(User user) async {
    const String mutation = r'''
      mutation UpdateUser($input: UserInput!) {
        updateUser(input: $input) {
          id
          name
          email
        }
      }
    ''';

    return await graphQLMutation<User>(
      mutation,
      variables: {'input': user.toJson()},
      dataKey: 'updateUser',
      fromJson: (json) => User.fromJson(json),
    );
  }
}

// -----------------------------------------------------------------------------
// 3. UI Implementation
// -----------------------------------------------------------------------------
void main() {
  // Define translation function
  String translate(String key) {
    const translations = {
      'no_internet_connection': 'No Internet Connection',
      'something_went_wrong_please_try_again': 'Something went wrong',
    };
    return translations[key] ?? key;
  }

  // Initialize DioServices
  DioServices.instance.init(
    DioConfig(
      baseUrl: 'https://jsonplaceholder.typicode.com',
      getToken: () => 'dummy_token',
      translate: translate,
      onTokenExpired: () => debugPrint('Token expired!'),
      onConnectionError: () => debugPrint('Connection error!'),
    ),
  );

  runApp(const MaterialApp(home: NetworkingExamplePage()));
}

class NetworkingExamplePage extends StatefulWidget {
  const NetworkingExamplePage({super.key});

  @override
  State<NetworkingExamplePage> createState() => _NetworkingExamplePageState();
}

class _NetworkingExamplePageState extends State<NetworkingExamplePage> {
  final UserRepository _repository = UserRepository();
  String _log = 'Ready to test...';
  bool _isLoading = false;

  void _clearLog() => setState(() => _log = 'Ready to test...');

  void _logger(String message) {
    setState(() => _log = '$message\n\n$_log');
  }

  Future<void> _runTest(
    String name,
    Future<Either<HelperResponse, dynamic>> Function() action,
  ) async {
    setState(() => _isLoading = true);
    _logger('--- Testing $name ---');

    final result = await action();

    result.fold(
      (error) => _logger('❌ Error: [${error.statusCode}] ${error.message}'),
      (data) {
        if (data is User) {
          _logger('✅ Success: User(id: ${data.id}, name: ${data.name})');
        } else {
          _logger('✅ Success: $data');
        }
      },
    );

    setState(() => _isLoading = false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('REST & GraphQL Example')),
      body: Column(
        children: [
          Expanded(
            flex: 2,
            child: Container(
              width: double.infinity,
              color: Colors.black87,
              padding: const EdgeInsets.all(16),
              child: SingleChildScrollView(
                child: Text(
                  _log,
                  style: const TextStyle(
                    color: Colors.greenAccent,
                    fontFamily: 'Courier',
                  ),
                ),
              ),
            ),
          ),
          if (_isLoading) const LinearProgressIndicator(),
          Expanded(
            flex: 3,
            child: ListView(
              padding: const EdgeInsets.all(16),
              children: [
                const Text(
                  'REST API Tests',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
                ),
                const SizedBox(height: 10),
                ElevatedButton.icon(
                  onPressed: () => _runTest(
                    'REST GET User (ID: 1)',
                    () => _repository.getUserREST('1'),
                  ),
                  icon: const Icon(Icons.download),
                  label: const Text('GET Request (Fetch User)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.blue.shade100,
                  ),
                ),
                const SizedBox(height: 10),
                ElevatedButton.icon(
                  onPressed: () => _runTest(
                    'REST POST User',
                    () => _repository.createUserREST(
                      User(id: 0, name: 'New User', email: 'test@example.com'),
                    ),
                  ),
                  icon: const Icon(Icons.upload),
                  label: const Text('POST Request (Create User)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.green.shade100,
                  ),
                ),
                const Divider(height: 40),
                const Text(
                  'GraphQL Tests',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
                ),
                const Text(
                  '(Note: These will fail on JSONPlaceholder)',
                  style: TextStyle(color: Colors.grey, fontSize: 12),
                ),
                const SizedBox(height: 10),
                ElevatedButton.icon(
                  onPressed: () => _runTest(
                    'GraphQL Query',
                    () => _repository.getUserGraphQL('1'),
                  ),
                  icon: const Icon(Icons.search),
                  label: const Text('GraphQL Query (Fetch User)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.purple.shade100,
                  ),
                ),
                const SizedBox(height: 10),
                ElevatedButton.icon(
                  onPressed: () => _runTest(
                    'GraphQL Mutation',
                    () => _repository.updateUserGraphQL(
                      User(id: 1, name: 'Updated Name'),
                    ),
                  ),
                  icon: const Icon(Icons.edit),
                  label: const Text('GraphQL Mutation (Update User)'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.orange.shade100,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _clearLog,
        child: const Icon(Icons.cleaning_services),
      ),
    );
  }
}
4
likes
0
points
274
downloads

Publisher

unverified uploader

Weekly Downloads

A robust, solid-compliant networking layer using Dio.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

dartz, dio, equatable, flutter

More

Packages that depend on networking_layer