backfit_generator 0.0.2+3
backfit_generator: ^0.0.2+3 copied to clipboard

Source code generator for Backfit package.

Backfit_Generator #

Backfit is a Retrofit inspired HTTP Client and API Service generator for Dart. This package works with its companion package called backfit.

Installation #

Add the following to pubspec.yaml


dependencies:
  backfit: <latest_version>

dev_dependencies:
  backfit_generator: <latest_version>
  build_runner: <latest_version>

Usage #

First create a BackFit client


import 'package:backfit/backfit.dart';

final client = BackfitClient(
    baseUrl: 'https://jsonplaceholder.typicode.com',
    interceptors: [HttpLogger()]);

Then create an interface annotated with BackfitService annotation, it takes base end point as an optional parameter.

posts_service.dart


import 'package:backfit/backfit.dart';

part 'posts_service.backfit.dart';

@BackfitService()
abstract class Posts {}

As per your API requirement create a model with serialization support. In this example, I am using freezed and json_serializable for it, however these are not necessary. You just need a toJson() method and fromJson factory or static method inside the model class

my_post.dart


import 'package:freezed_annotation/freezed_annotation.dart';

part 'my_post.freezed.dart';
part 'my_post.g.dart';

@freezed
class MyPost with _$MyPost {
  const factory MyPost({
    required int userId,
    required int id,
    required String title,
    required String body,
  }) = _MyPost;

  factory MyPost.fromJson(Map<String, dynamic> json) => _$MyPostFromJson(json);
}

Now go back to the api_service interface and add an abstract method defining the return type, endpoint and signature.

posts_service.dart


import 'package:backfit/backfit.dart';
import 'my_post.dart';

part 'posts_service.backfit.dart';

@BackfitService()
abstract class Posts {
  @Get('posts')
  Future<Response<List<MyPost>>> postsByUserId(@Query('userId') String userId); 
}

Note that the Response class mentioned here is from Backfit and not http and as such takes in your Model class as a type parameter for auto parsing.

Now if you are using flutter run -

  flutter pub run build_runner [build|watch] [OPTIONAL --delete-conflicting-outputs]

Or if you are working with dart only run -

  pub run build_runner [build|watch] [OPTIONAL --delete-conflicting-outputs]

This generates the following code -

posts_service.backfit.dart


// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'posts_service.dart';

// **************************************************************************
// BackfitGenerator
// **************************************************************************

class PostsService extends Posts with _$Posts {
  PostsService() {
    _client = BackfitClient();
  }

  PostsService.withClient(BackfitClient client) {
    _client = client;
  }
}

mixin _$Posts implements Posts {
  BackfitClient? _client;

  @override
  Future<Response<List<MyPost>>> postsByUserId(String userId) async {
    final res = await _client!
        .get(Uri.parse('${_client!.baseUrl}/posts/posts?userId=$userId'));

    return Response(
      data: res.body.isNotEmpty
          ? (json.decode(res.body) as List)
              .map((it) => MyPost.fromJson(it))
              .toList()
          : null,
      statusCode: res.statusCode,
      reasonPhrase: res.reasonPhrase,
      headers: HttpHeaders.fromMap(res.headers),
    );
  }
}

What's Next? Consume the Api Service wherever you want like this -


//in some injector 
final postsService = PostsService.withClient(client);


//inside a consumer
postsService.postsByUserId('1').catchError((e) {
  print(e.toString());
});

Contributing #

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License #

MIT