retrofit_craft 0.5.0
retrofit_craft: ^0.5.0 copied to clipboard
Annotations to declare a grouped, versioned retrofit API client aggregator for the riverpod_craft / craft_runner ecosystem.
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 #
- Declare an enum of your gateways with a
baseUrlfield (per the enhanced enum pattern). Convention: name itEntry. - Declare an enum of your versions. Convention: name it
Version. - Annotate each retrofit abstract class with
@Api(entry: Entry.<name>, version: Version.<vN>)alongside@RestApi(). retrofit_craft_pluginauto-scans the project and emits oneAppApisource 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.