Skip to content

Commit

Permalink
🔖 release v7.0.1 (#465)
Browse files Browse the repository at this point in the history
# chopper

## 7.0.1

- Refactor ChopperClient constructor
- Refactor ChopperClient.getService
- Refactor CurlInterceptor

# chopper_generator

## 7.0.1

- Add final class modifier to generated Chopper API implementation
  • Loading branch information
techouse authored Aug 3, 2023
1 parent 85079b2 commit 203e64d
Show file tree
Hide file tree
Showing 19 changed files with 127 additions and 106 deletions.
40 changes: 7 additions & 33 deletions .github/workflows/dart.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Created with package:mono_repo v6.5.5
# Created with package:mono_repo v6.5.7
name: Dart CI
on:
push:
Expand Down Expand Up @@ -37,20 +37,20 @@ jobs:
name: Checkout repository
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- name: mono_repo self validate
run: dart pub global activate mono_repo 6.5.5
run: dart pub global activate mono_repo 6.5.7
- name: mono_repo self validate
run: dart pub global run mono_repo generate --validate
job_002:
name: "analyze_and_format; PKG: chopper; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
name: "analyze_and_format; PKGS: chopper, chopper_built_value, chopper_generator; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
runs-on: ubuntu-latest
steps:
- name: Cache Pub hosted dependencies
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8
with:
path: "~/.pub-cache/hosted"
key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper;commands:format-analyze"
key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper-chopper_built_value-chopper_generator;commands:format-analyze"
restore-keys: |
os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper
os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper-chopper_built_value-chopper_generator
os:ubuntu-latest;pub-cache-hosted;sdk:stable
os:ubuntu-latest;pub-cache-hosted
os:ubuntu-latest
Expand All @@ -74,29 +74,6 @@ jobs:
run: dart analyze --fatal-infos .
if: "always() && steps.chopper_pub_upgrade.conclusion == 'success'"
working-directory: chopper
needs:
- job_001
job_003:
name: "analyzer_and_format; PKGS: chopper_built_value, chopper_generator; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
runs-on: ubuntu-latest
steps:
- name: Cache Pub hosted dependencies
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8
with:
path: "~/.pub-cache/hosted"
key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper_built_value-chopper_generator;commands:format-analyze"
restore-keys: |
os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:chopper_built_value-chopper_generator
os:ubuntu-latest;pub-cache-hosted;sdk:stable
os:ubuntu-latest;pub-cache-hosted
os:ubuntu-latest
- name: Setup Dart SDK
uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
with:
sdk: stable
- id: checkout
name: Checkout repository
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- id: chopper_built_value_pub_upgrade
name: chopper_built_value; dart pub upgrade
run: dart pub upgrade
Expand Down Expand Up @@ -125,8 +102,7 @@ jobs:
working-directory: chopper_generator
needs:
- job_001
- job_002
job_004:
job_003:
name: "unit_test; PKGS: chopper, chopper_built_value, chopper_generator; `dart pub global run coverage:test_with_coverage`"
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -197,8 +173,7 @@ jobs:
needs:
- job_001
- job_002
- job_003
job_005:
job_004:
name: "unit_test; PKGS: chopper, chopper_built_value; `dart test -p chrome`"
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -240,4 +215,3 @@ jobs:
needs:
- job_001
- job_002
- job_003
6 changes: 6 additions & 0 deletions chopper/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 7.0.1

- Refactor ChopperClient constructor
- Refactor ChopperClient.getService
- Refactor CurlInterceptor

## 7.0.0

- Require Dart 3.0 or later
Expand Down
2 changes: 1 addition & 1 deletion chopper/example/definition.chopper.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 36 additions & 35 deletions chopper/lib/src/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import 'package:chopper/src/utils.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

Type _typeOf<T>() => T;

@visibleForTesting
const List<Type> allowedInterceptorsType = [
RequestInterceptor,
Expand Down Expand Up @@ -47,11 +45,13 @@ base class ChopperClient {
/// (statusCode < 200 || statusCode >= 300\).
final ErrorConverter? errorConverter;

final Map<Type, ChopperService> _services = {};
final _requestInterceptors = [];
final _responseInterceptors = [];
final _requestController = StreamController<Request>.broadcast();
final _responseController = StreamController<Response>.broadcast();
late final Map<Type, ChopperService> _services;
late final List _requestInterceptors;
late final List _responseInterceptors;
final StreamController<Request> _requestController =
StreamController<Request>.broadcast();
final StreamController<Response> _responseController =
StreamController<Response>.broadcast();

final bool _clientIsInternal;

Expand Down Expand Up @@ -114,44 +114,46 @@ base class ChopperClient {
ChopperClient({
Uri? baseUrl,
http.Client? client,
Iterable interceptors = const [],
Iterable? interceptors,
this.authenticator,
this.converter,
this.errorConverter,
Iterable<ChopperService> services = const [],
Iterable<ChopperService>? services,
}) : assert(
baseUrl == null || !baseUrl.hasQuery,
'baseUrl should not contain query parameters.'
'Use a request interceptor to add default query parameters'),
baseUrl == null || !baseUrl.hasQuery,
'baseUrl should not contain query parameters. '
'Use a request interceptor to add default query parameters',
),
baseUrl = baseUrl ?? Uri(),
httpClient = client ?? http.Client(),
_clientIsInternal = client == null {
if (!interceptors.every(_isAnInterceptor)) {
throw ArgumentError(
'Unsupported type for interceptors, it only support the following types:\n'
'${allowedInterceptorsType.join('\n - ')}',
);
}

_requestInterceptors.addAll(interceptors.where(_isRequestInterceptor));
_responseInterceptors.addAll(interceptors.where(_isResponseInterceptor));

services.toSet().forEach((s) {
s.client = this;
_services[s.definitionType] = s;
});
_clientIsInternal = client == null,
assert(
interceptors?.every(_isAnInterceptor) ?? true,
'Unsupported type for interceptors, it only support the following types:\n'
' - ${allowedInterceptorsType.join('\n - ')}',
),
_requestInterceptors = [
...?interceptors?.where(_isRequestInterceptor),
],
_responseInterceptors = [
...?interceptors?.where(_isResponseInterceptor),
] {
_services = <Type, ChopperService>{
for (final ChopperService service in services?.toSet() ?? [])
service.definitionType: service..client = this
};
}

bool _isRequestInterceptor(value) =>
static bool _isRequestInterceptor(value) =>
value is RequestInterceptor || value is RequestInterceptorFunc;

bool _isResponseInterceptor(value) =>
static bool _isResponseInterceptor(value) =>
value is ResponseInterceptor ||
value is ResponseInterceptorFunc1 ||
value is ResponseInterceptorFunc2 ||
value is DynamicResponseInterceptorFunc;

bool _isAnInterceptor(value) =>
static bool _isAnInterceptor(value) =>
_isResponseInterceptor(value) || _isRequestInterceptor(value);

/// Retrieve any service included in the [ChopperClient]
Expand All @@ -168,15 +170,14 @@ base class ChopperClient {
/// final todoService = chopper.getService<TodosListService>();
/// ```
ServiceType getService<ServiceType extends ChopperService>() {
final Type serviceType = _typeOf<ServiceType>();
if (serviceType == dynamic || serviceType == ChopperService) {
if (ServiceType == dynamic || ServiceType == ChopperService) {
throw Exception(
'Service type should be provided, `dynamic` is not allowed.',
);
}
final ChopperService? service = _services[serviceType];
final ChopperService? service = _services[ServiceType];
if (service == null) {
throw Exception('Service of type \'$serviceType\' not found.');
throw Exception("Service of type '$ServiceType' not found.");
}

return service as ServiceType;
Expand All @@ -185,7 +186,7 @@ base class ChopperClient {
Future<Request> _encodeRequest(Request request) async =>
converter?.convertRequest(request) ?? request;

Future<Response<BodyType>> _decodeResponse<BodyType, InnerType>(
static Future<Response<BodyType>> _decodeResponse<BodyType, InnerType>(
Response response,
Converter withConverter,
) async =>
Expand Down
31 changes: 13 additions & 18 deletions chopper/lib/src/interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,32 +137,27 @@ class CurlInterceptor implements RequestInterceptor {
@override
Future<Request> onRequest(Request request) async {
final http.BaseRequest baseRequest = await request.toBaseRequest();
final String method = baseRequest.method;
final String url = baseRequest.url.toString();
final Map<String, String> headers = baseRequest.headers;
String curl = 'curl -v -X $method';
headers.forEach((k, v) {
curl += ' -H \'$k: $v\'';
});
final List<String> curlParts = ['curl -v -X ${baseRequest.method}'];
for (final MapEntry<String, String> header in baseRequest.headers.entries) {
curlParts.add("-H '${header.key}: ${header.value}'");
}
// this is fairly naive, but it should cover most cases
if (baseRequest is http.Request) {
final body = baseRequest.body;
final String body = baseRequest.body;
if (body.isNotEmpty) {
curl += ' -d \'$body\'';
curlParts.add("-d '$body'");
}
}
if (baseRequest is http.MultipartRequest) {
final fields = baseRequest.fields;
final files = baseRequest.files;
fields.forEach((k, v) {
curl += ' -f \'$k: $v\'';
});
for (var file in files) {
curl += ' -f \'${file.field}: ${file.filename ?? ''}\'';
for (final MapEntry<String, String> field in baseRequest.fields.entries) {
curlParts.add("-f '${field.key}: ${field.value}'");
}
for (final http.MultipartFile file in baseRequest.files) {
curlParts.add("-f '${file.field}: ${file.filename ?? ''}'");
}
}
curl += ' "$url"';
chopperLogger.info(curl);
curlParts.add('"${baseRequest.url}"');
chopperLogger.info(curlParts.join(' '));

return request;
}
Expand Down
4 changes: 1 addition & 3 deletions chopper/lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,4 @@ final class _Pair<A, B> with EquatableMixin {

bool isTypeOf<ThisType, OfType>() => _Instance<ThisType>() is _Instance<OfType>;

class _Instance<T> {
//
}
final class _Instance<T> {}
2 changes: 1 addition & 1 deletion chopper/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: chopper
description: Chopper is an http client generator using source_gen, inspired by Retrofit
version: 7.0.0
version: 7.0.1
documentation: https://hadrien-lejard.gitbook.io/chopper
repository: https://github.com/lejard-h/chopper

Expand Down
54 changes: 48 additions & 6 deletions chopper/test/base_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ void main() {
);

group('Base', () {
test('getService', () async {
final httpClient = MockClient(
(_) async => http.Response('get response', 200),
);

final chopper = buildClient(httpClient);
final service = chopper.getService<HttpTestService>();

expect(service, isNotNull);
expect(service, isA<HttpTestService>());
});

test('get service errors', () async {
final chopper = ChopperClient(
baseUrl: baseUrl,
Expand All @@ -38,7 +50,7 @@ void main() {
} on Exception catch (e) {
expect(
e.toString(),
equals('Exception: Service of type \'HttpTestService\' not found.'),
equals("Exception: Service of type 'HttpTestService' not found."),
);
}

Expand Down Expand Up @@ -635,20 +647,50 @@ void main() {
});

test('wrong type for interceptor', () {
expect(
() => ChopperClient(interceptors: [(bool foo) => 'bar']),
throwsA(isA<AssertionError>()),
);

try {
ChopperClient(
interceptors: [
(bool foo) => 'bar',
],
);
} on ArgumentError catch (e) {
} on AssertionError catch (error) {
expect(
e.toString(),
'Invalid argument(s): Unsupported type for interceptors, it only support the following types:\n'
'${allowedInterceptorsType.join('\n - ')}',
error.toString(),
contains(
'Unsupported type for interceptors, it only support the following types:\n'
' - ${allowedInterceptorsType.join('\n - ')}',
),
);
}
});
}, testOn: 'vm');

test('wrong type for interceptor', () {
expect(
() => ChopperClient(interceptors: [(bool foo) => 'bar']),
throwsA(isA<AssertionError>()),
);

try {
ChopperClient(
interceptors: [
(bool foo) => 'bar',
],
);
} on AssertionError catch (error) {
expect(
error.toString(),
contains(
'Unsupported type for interceptors, it only support the following types:\\n'
' - ${allowedInterceptorsType.join('\\n - ')}',
),
);
}
}, testOn: 'browser');

test('Query Map 1', () async {
final httpClient = MockClient((request) async {
Expand Down
2 changes: 1 addition & 1 deletion chopper/test/test_service.chopper.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion chopper_built_value/mono_pkg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sdk:
- stable

stages:
- analyzer_and_format:
- analyze_and_format:
- group:
- format
- analyze: --fatal-infos .
Expand Down
Loading

0 comments on commit 203e64d

Please sign in to comment.