rest_client_builder 1.2.0
rest_client_builder: ^1.2.0 copied to clipboard
A Clean Architecture code-generation framework for building typed REST API clients in Dart and Flutter using annotations and build_runner.
example/lib/main.dart
import 'dart:convert';
import 'package:rest_client_builder/rest_client_builder.dart';
import 'demo_api.dart';
import 'user.dart';
/// Production-style example of `rest_client_builder`.
///
/// Runs offline with [CallbackRestClient] so CI / local demos need no network.
/// Swap in `buildExampleClient()` from `app_config.dart` for real Dio HTTP.
void main() async {
final sampleUser = {
'id': '1',
'user_name': 'Ada',
'role': 'admin',
'createdAt': '2024-01-02T03:04:05.000Z',
'tags': ['dart', 'flutter'],
'scores': {'chess': 2100},
'address': {'city': 'London', 'country': 'UK'},
};
final requests = <RestRequest>[];
final client = CallbackRestClient(
onExecute: (request) async {
requests.add(request);
if (request.method == HttpMethodNames.delete) {
return Success(
BasicRestResponse(statusCode: 204, request: request),
);
}
if (request.bodyType == RestBodyType.multipart) {
return Success(
BasicRestResponse(
statusCode: 200,
request: request,
data: sampleUser,
),
);
}
if (request.path.contains('/users') &&
request.method == HttpMethodNames.get &&
!request.path.contains('/users/')) {
return Success(
BasicRestResponse(
statusCode: 200,
request: request,
data: [sampleUser],
),
);
}
return Success(
BasicRestResponse(
statusCode: 200,
request: request,
data: sampleUser,
),
);
},
);
final api = DemoApi(client);
await _demoCrud(api);
await _demoMultipartCancelProgress(api);
await _demoLoginExcludesAuth(api);
// ignore: avoid_print
print('example ok — ${requests.length} requests exercised');
// ignore: avoid_print
print('endpoints: ${DemoApiDocs.endpoints.join(', ')}');
}
Future<void> _demoCrud(DemoApi api) async {
final user = User(
id: '1',
name: 'Ada',
role: Role.admin,
createdAt: DateTime.utc(2024, 1, 2, 3, 4, 5),
tags: const ['dart'],
scores: const {'chess': 2100},
);
final get = await api.getUser('1', expand: 'address');
get.getOrThrow();
final list = await api.listUsers({'page': 1});
expectTrue(list.getOrThrow().length == 1);
final created = await api.createUser(user);
expectTrue(created.getOrThrow().name == 'Ada');
final replaced = await api.replaceUser('1', user);
replaced.getOrThrow();
final patched = await api.patchUser('1', {'user_name': 'Ada Lovelace'});
patched.getOrThrow();
final deleted = await api.deleteUser('1');
expectTrue(deleted.isSuccess);
}
Future<void> _demoMultipartCancelProgress(DemoApi api) async {
final token = BasicCancelToken();
final progress = <String>[];
final bytes = utf8.encode('fake-image-bytes');
final part = RestPart.fromBytes(
name: 'file',
bytes: bytes,
fileName: 'avatar.png',
contentType: 'image/png',
);
// Also exercise Base64 factory (no dart:io File).
final roundTrip = RestPart.fromBase64(
name: 'file',
base64: base64Encode(bytes),
fileName: 'avatar.png',
contentType: 'image/png',
);
expectTrue(roundTrip.bytes.length == bytes.length);
final result = await api.uploadAvatar(
part,
'profile',
cancelToken: token,
onSendProgress: (count, total) => progress.add('up:$count/$total'),
onReceiveProgress: (count, total) => progress.add('down:$count/$total'),
);
result.getOrThrow();
expectTrue(!token.isCancelled);
}
Future<void> _demoLoginExcludesAuth(DemoApi api) async {
final result = await api.login('ada@example.com', 'secret');
result.getOrThrow();
}
void expectTrue(bool value) {
if (!value) {
throw StateError('example assertion failed');
}
}