retrofit_craft

Annotations for declaring a grouped, versioned retrofit API client aggregator (AppApi), generated by retrofit_craft_plugin via craft_runner.

retrofit + retrofit_generator still produce the per-endpoint HTTP implementations (*.g.dart). retrofit_craft only generates the aggregation layer on top, giving you:

final api = AppApi(dio: Dio());
api.identity.auth.v1.login(phone: '...', password: '...');
api.consumer.order.v2.checkout(cart);
api.identity.health.check();   // no version layer when @Api has no version

How it works

  1. Declare an enum of your gateways with a baseUrl field (per the enhanced enum pattern). Convention: name it Entry.
  2. Declare an enum of your versions. Convention: name it Version.
  3. Annotate each retrofit abstract class with @Api(entry: Entry.<name>, version: Version.<vN>) alongside @RestApi().
  4. retrofit_craft_plugin auto-scans the project and emits one AppApi source file with nested groups, version wrappers, and direct entries.

Annotation

// from package:retrofit_craft/retrofit_craft.dart
class Api {
  const Api({this.entry, this.version});
  final Object? entry;
  final Object? version;
}

Both entry and version are Object? so any const expression works. The scanner inspects the source — it expects <Prefix>.<name> shape (a property access on an enum or a class with static const fields).

Example

// lib/app/api/entries.dart
enum Entry {
  identity('https://identity.example.com/api/'),
  consumer('https://consumer.example.com/api/');

  const Entry(this.baseUrl);
  final String baseUrl;
}

// lib/app/api/versions.dart
enum Version { v1, v2, v3 }

// lib/features/auth/auth_api_v1.dart
@Api(entry: Entry.identity, version: Version.v1)
@RestApi()
abstract class AuthApiV1 {
  factory AuthApiV1(Dio dio, {String? baseUrl}) = _AuthApiV1;
  @POST('/login')
  Future<void> login({required String phone, required String password});
}

Optional: let the Version enum drive the URL path

If your Version enum declares a final String path field, retrofit_craft concatenates it onto the entry's baseUrl for every versioned wrapper. Method paths can then drop their version prefix — the version is declared in one place only:

enum Version {
  v1('v1/'),
  v2('v2/'),
  v3('v3/');

  const Version(this.path);
  final String path;
}

@Api(entry: Entry.identity, version: Version.v1)
@RestApi()
abstract class AuthApiV1 {
  factory AuthApiV1(Dio dio, {String? baseUrl}) = _AuthApiV1;

  // No leading `/` and no `v1/` — both come from the baseUrl now.
  @POST('login')
  Future<void> login({required String phone, required String password});
}

Generated:

late final v1 = AuthApiV1(
  _dio,
  baseUrl: '${Entry.identity.baseUrl}${Version.v1.path}',
);

This is opt-in: if Version has no path field (or the field isn't a String), the generator falls back to today's behaviour — baseUrl: Entry.identity.baseUrl — byte-for-byte. Unversioned classes (those whose @Api(...) omits the version: arg) always use the bare baseUrl regardless of the field's presence.

Convention: include the trailing slash on both Entry.baseUrl and Version.path. retrofit_craft concatenates verbatim — what you write is what you get.

Generated (excerpt):

class AppApi {
  AppApi({required this.dio});
  final Dio dio;
  late final identity = _IdentityEntry(dio);
}

class _IdentityEntry {
  _IdentityEntry(this._dio);
  final Dio _dio;
  late final auth = _IdentityAuthVersions(_dio);
}

class _IdentityAuthVersions {
  _IdentityAuthVersions(this._dio);
  final Dio _dio;
  late final v1 = AuthApiV1(_dio, baseUrl: Entry.identity.baseUrl);
}

Optional config (riverpod_craft.yaml)

retrofit_craft:
  default_entry: Entry.identity        # used when @Api() omits entry
  default_version: Version.v1          # used when @Api() omits version
  entry_path: lib/app/api/entries.dart
  version_path: lib/app/api/versions.dart
  output: lib/app/app_api.craft.dart   # output (must end .craft.dart)

See examples/retrofit_aggregator for a complete, working setup.

Status

Alpha (0.2.0), part of the riverpod_craft ecosystem.

Libraries

retrofit_craft
Annotations for declaring a grouped, versioned retrofit API client aggregator (AppApi), generated by retrofit_craft_plugin via craft_runner.