Browse Source

dynamite, dynamite_runtime, nextcloud: move http client to dynamite_runtime

pull/413/head
Nikolas Rimikis 1 year ago
parent
commit
e856d557ea
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 251
      packages/dynamite/dynamite/lib/src/openapi_builder.dart
  2. 1
      packages/dynamite/dynamite_runtime/lib/http_client.dart
  3. 144
      packages/dynamite/dynamite_runtime/lib/src/http_client.dart
  4. 2
      packages/dynamite/dynamite_runtime/pubspec.yaml
  5. 115
      packages/nextcloud/lib/src/nextcloud.openapi.dart
  6. 1
      packages/nextcloud/pubspec.yaml

251
packages/dynamite/dynamite/lib/src/openapi_builder.dart

@ -67,48 +67,13 @@ class OpenAPIBuilder implements Builder {
"import 'package:built_value/json_object.dart';", "import 'package:built_value/json_object.dart';",
"import 'package:built_value/serializer.dart';", "import 'package:built_value/serializer.dart';",
"import 'package:built_value/standard_json_plugin.dart';", "import 'package:built_value/standard_json_plugin.dart';",
"import 'package:cookie_jar/cookie_jar.dart';",
"import 'package:dynamite_runtime/content_string.dart';", "import 'package:dynamite_runtime/content_string.dart';",
"import 'package:universal_io/io.dart';", "import 'package:dynamite_runtime/http_client.dart';",
'', '',
"export 'package:cookie_jar/cookie_jar.dart';", "export 'package:dynamite_runtime/http_client.dart';",
'', '',
"part '${p.basename(outputId.changeExtension('.g.dart').path)}';", "part '${p.basename(outputId.changeExtension('.g.dart').path)}';",
'', '',
Extension(
(final b) => b
..name = '${prefix}HttpClientResponseBody'
..on = refer('HttpClientResponse')
..methods.addAll([
Method(
(final b) => b
..name = 'bodyBytes'
..returns = refer('Future<Uint8List>')
..type = MethodType.getter
..modifier = MethodModifier.async
..body = const Code(
'''
final chunks = await toList();
if (chunks.isEmpty) {
return Uint8List(0);
}
return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element]));
''',
),
),
Method(
(final b) => b
..name = 'body'
..returns = refer('Future<String>')
..type = MethodType.getter
..modifier = MethodModifier.async
..lambda = true
..body = const Code(
'utf8.decode(await bodyBytes)',
),
),
]),
).accept(emitter).toString(),
Class( Class(
(final b) => b (final b) => b
..name = '${prefix}Response' ..name = '${prefix}Response'
@ -116,20 +81,7 @@ class OpenAPIBuilder implements Builder {
refer('T'), refer('T'),
refer('U'), refer('U'),
]) ])
..fields.addAll([ ..extend = refer('DynamiteResponse<T, U>')
Field(
(final b) => b
..name = 'data'
..type = refer('T')
..modifier = FieldModifier.final$,
),
Field(
(final b) => b
..name = 'headers'
..type = refer('U')
..modifier = FieldModifier.final$,
),
])
..constructors.add( ..constructors.add(
Constructor( Constructor(
(final b) => b (final b) => b
@ -138,7 +90,7 @@ class OpenAPIBuilder implements Builder {
(final name) => Parameter( (final name) => Parameter(
(final b) => b (final b) => b
..name = name ..name = name
..toThis = true, ..toSuper = true,
), ),
), ),
), ),
@ -157,61 +109,10 @@ class OpenAPIBuilder implements Builder {
), ),
), ),
).accept(emitter).toString(), ).accept(emitter).toString(),
Class(
(final b) => b
..name = 'RawResponse'
..fields.addAll([
Field(
(final b) => b
..name = 'statusCode'
..type = refer('int')
..modifier = FieldModifier.final$,
),
Field(
(final b) => b
..name = 'headers'
..type = refer('Map<String, String>')
..modifier = FieldModifier.final$,
),
Field(
(final b) => b
..name = 'body'
..type = refer('Uint8List')
..modifier = FieldModifier.final$,
),
])
..constructors.add(
Constructor(
(final b) => b
..requiredParameters.addAll(
['statusCode', 'headers', 'body'].map(
(final name) => Parameter(
(final b) => b
..name = name
..toThis = true,
),
),
),
),
)
..methods.add(
Method(
(final b) => b
..name = 'toString'
..returns = refer('String')
..annotations.add(refer('override'))
..lambda = true
..body = const Code(
r"'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})'",
),
),
),
).accept(emitter).toString(),
Class( Class(
(final b) => b (final b) => b
..name = '${prefix}ApiException' ..name = '${prefix}ApiException'
..extend = refer('RawResponse') ..extend = refer('DynamiteApiException')
..implements.add(refer('Exception'))
..constructors.addAll( ..constructors.addAll(
[ [
Constructor( Constructor(
@ -255,27 +156,6 @@ class OpenAPIBuilder implements Builder {
), ),
), ),
).accept(emitter).toString(), ).accept(emitter).toString(),
if (hasAnySecurity) ...[
Class(
(final b) => b
..name = '${prefix}Authentication'
..abstract = true
..methods.addAll([
Method(
(final b) => b
..name = 'id'
..type = MethodType.getter
..returns = refer('String'),
),
Method(
(final b) => b
..name = 'headers'
..type = MethodType.getter
..returns = refer('Map<String, String>'),
),
]),
).accept(emitter).toString(),
],
]; ];
if (spec.components?.securitySchemes != null) { if (spec.components?.securitySchemes != null) {
@ -291,7 +171,7 @@ class OpenAPIBuilder implements Builder {
final fields = ['username', 'password']; final fields = ['username', 'password'];
b b
..name = '${prefix}HttpBasicAuthentication' ..name = '${prefix}HttpBasicAuthentication'
..extend = refer('${prefix}Authentication') ..extend = refer('DynamiteAuthentication')
..constructors.add( ..constructors.add(
Constructor( Constructor(
(final b) => b (final b) => b
@ -352,7 +232,7 @@ class OpenAPIBuilder implements Builder {
(final b) { (final b) {
b b
..name = '${prefix}HttpBearerAuthentication' ..name = '${prefix}HttpBearerAuthentication'
..extend = refer('${prefix}Authentication') ..extend = refer('DynamiteAuthentication')
..constructors.add( ..constructors.add(
Constructor( Constructor(
(final b) => b (final b) => b
@ -437,42 +317,7 @@ class OpenAPIBuilder implements Builder {
(final b) { (final b) {
if (isRootClient) { if (isRootClient) {
b b
..fields.addAll([ ..extend = refer('DynamiteClient')
Field(
(final b) => b
..name = 'baseURL'
..type = refer('String')
..modifier = FieldModifier.final$,
),
Field(
(final b) => b
..name = 'baseHeaders'
..type = refer('Map<String, String>')
..modifier = FieldModifier.final$
..late = true,
),
Field(
(final b) => b
..name = 'httpClient'
..type = refer('HttpClient')
..modifier = FieldModifier.final$
..late = true,
),
Field(
(final b) => b
..name = 'cookieJar'
..type = refer('CookieJar?')
..modifier = FieldModifier.final$,
),
if (hasAnySecurity) ...[
Field(
(final b) => b
..name = 'authentications'
..type = refer('List<${prefix}Authentication>')
..modifier = FieldModifier.final$,
),
],
])
..constructors.add( ..constructors.add(
Constructor( Constructor(
(final b) => b (final b) => b
@ -480,109 +325,45 @@ class OpenAPIBuilder implements Builder {
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'baseURL' ..name = 'baseURL'
..toThis = true, ..toSuper = true,
), ),
) )
..optionalParameters.addAll([ ..optionalParameters.addAll([
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'baseHeaders' ..name = 'baseHeaders'
..type = refer('Map<String, String>?') ..toSuper = true
..named = true, ..named = true,
), ),
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'userAgent' ..name = 'userAgent'
..type = refer('String?') ..toSuper = true
..named = true, ..named = true,
), ),
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'httpClient' ..name = 'httpClient'
..type = refer('HttpClient?') ..toSuper = true
..named = true, ..named = true,
), ),
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'cookieJar' ..name = 'cookieJar'
..toThis = true ..toSuper = true
..named = true, ..named = true,
), ),
if (hasAnySecurity) ...[ if (hasAnySecurity) ...[
Parameter( Parameter(
(final b) => b (final b) => b
..name = 'authentications' ..name = 'authentications'
..toThis = true ..toSuper = true
..named = true ..named = true,
..defaultTo = const Code('const []'),
), ),
], ],
]) ]),
..body = const Code('''
this.baseHeaders = {
...?baseHeaders,
};
this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent;
'''),
),
)
..methods.addAll([
Method(
(final b) => b
..name = 'doRequest'
..returns = refer('Future<RawResponse>')
..modifier = MethodModifier.async
..requiredParameters.addAll([
Parameter(
(final b) => b
..name = 'method'
..type = refer('String'),
),
Parameter(
(final b) => b
..name = 'path'
..type = refer('String'),
),
Parameter(
(final b) => b
..name = 'headers'
..type = refer('Map<String, String>'),
),
Parameter(
(final b) => b
..name = 'body'
..type = refer('Uint8List?'),
), ),
])
..body = const Code(r'''
final uri = Uri.parse('$baseURL$path');
final request = await httpClient.openUrl(method, uri);
for (final header in {...baseHeaders, ...headers}.entries) {
request.headers.add(header.key, header.value);
}
if (body != null) {
request.add(body.toList());
}
if (cookieJar != null) {
request.cookies.addAll(await cookieJar!.loadForRequest(uri));
}
final response = await request.close();
if (cookieJar != null) {
await cookieJar!.saveFromResponse(uri, response.cookies);
}
final responseHeaders = <String, String>{};
response.headers.forEach((final name, final values) {
responseHeaders[name] = values.last;
});
return RawResponse(
response.statusCode,
responseHeaders,
await response.bodyBytes,
); );
'''),
),
]);
} else { } else {
b b
..fields.add( ..fields.add(

1
packages/dynamite/dynamite_runtime/lib/http_client.dart

@ -0,0 +1 @@
export 'src/http_client.dart';

144
packages/dynamite/dynamite_runtime/lib/src/http_client.dart

@ -0,0 +1,144 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:universal_io/io.dart';
export 'package:cookie_jar/cookie_jar.dart';
extension DynamiteHttpClientResponseBody on HttpClientResponse {
Future<Uint8List> get bodyBytes async {
final chunks = await toList();
if (chunks.isEmpty) {
return Uint8List(0);
}
return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element]));
}
Future<String> get body async => utf8.decode(await bodyBytes);
}
class DynamiteResponse<T, U> {
DynamiteResponse(
this.data,
this.headers,
);
final T data;
final U headers;
@override
String toString() => 'DynamiteResponse(data: $data, headers: $headers)';
}
class RawResponse {
RawResponse(
this.statusCode,
this.headers,
this.body,
);
final int statusCode;
final Map<String, String> headers;
final Uint8List body;
@override
String toString() => 'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})';
}
class DynamiteApiException extends RawResponse implements Exception {
DynamiteApiException(
super.statusCode,
super.headers,
super.body,
);
@override
String toString() =>
'DynamiteApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})';
}
abstract class DynamiteAuthentication {
String get id;
Map<String, String> get headers;
}
class DynamiteHttpBasicAuthentication extends DynamiteAuthentication {
DynamiteHttpBasicAuthentication({
required this.username,
required this.password,
});
final String username;
final String password;
@override
String get id => 'basic_auth';
@override
Map<String, String> get headers => {
'Authorization': 'Basic ${base64.encode(utf8.encode('$username:$password'))}',
};
}
class DynamiteClient {
DynamiteClient(
this.baseURL, {
final Map<String, String>? baseHeaders,
final String? userAgent,
final HttpClient? httpClient,
this.cookieJar,
this.authentications = const [],
}) {
this.baseHeaders = {
...?baseHeaders,
};
this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent;
}
final String baseURL;
late final Map<String, String> baseHeaders;
late final HttpClient httpClient;
final CookieJar? cookieJar;
final List<DynamiteAuthentication> authentications;
Future<RawResponse> doRequest(
final String method,
final String path,
final Map<String, String> headers,
final Uint8List? body,
) async {
final uri = Uri.parse('$baseURL$path');
final request = await httpClient.openUrl(method, uri);
for (final header in {...baseHeaders, ...headers}.entries) {
request.headers.add(header.key, header.value);
}
if (body != null) {
request.add(body.toList());
}
if (cookieJar != null) {
request.cookies.addAll(await cookieJar!.loadForRequest(uri));
}
final response = await request.close();
if (cookieJar != null) {
await cookieJar!.saveFromResponse(uri, response.cookies);
}
final responseHeaders = <String, String>{};
response.headers.forEach((final name, final values) {
responseHeaders[name] = values.last;
});
return RawResponse(
response.statusCode,
responseHeaders,
await response.bodyBytes,
);
}
}

2
packages/dynamite/dynamite_runtime/pubspec.yaml

@ -7,6 +7,8 @@ environment:
dependencies: dependencies:
built_value: ^8.5.0 built_value: ^8.5.0
cookie_jar: ^4.0.5
universal_io: ^2.2.2
dev_dependencies: dev_dependencies:
build_runner: ^2.4.2 build_runner: ^2.4.2

115
packages/nextcloud/lib/src/nextcloud.openapi.dart

@ -8,58 +8,24 @@ import 'package:built_value/built_value.dart';
import 'package:built_value/json_object.dart'; import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart'; import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart'; import 'package:built_value/standard_json_plugin.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/content_string.dart';
import 'package:universal_io/io.dart'; import 'package:dynamite_runtime/http_client.dart';
export 'package:cookie_jar/cookie_jar.dart'; export 'package:dynamite_runtime/http_client.dart';
part 'nextcloud.openapi.g.dart'; part 'nextcloud.openapi.g.dart';
extension NextcloudHttpClientResponseBody on HttpClientResponse { class NextcloudResponse<T, U> extends DynamiteResponse<T, U> {
Future<Uint8List> get bodyBytes async {
final chunks = await toList();
if (chunks.isEmpty) {
return Uint8List(0);
}
return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element]));
}
Future<String> get body async => utf8.decode(await bodyBytes);
}
class NextcloudResponse<T, U> {
NextcloudResponse( NextcloudResponse(
this.data, super.data,
this.headers, super.headers,
); );
final T data;
final U headers;
@override @override
String toString() => 'NextcloudResponse(data: $data, headers: $headers)'; String toString() => 'NextcloudResponse(data: $data, headers: $headers)';
} }
class RawResponse { class NextcloudApiException extends DynamiteApiException {
RawResponse(
this.statusCode,
this.headers,
this.body,
);
final int statusCode;
final Map<String, String> headers;
final Uint8List body;
@override
String toString() => 'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})';
}
class NextcloudApiException extends RawResponse implements Exception {
NextcloudApiException( NextcloudApiException(
super.statusCode, super.statusCode,
super.headers, super.headers,
@ -77,12 +43,7 @@ class NextcloudApiException extends RawResponse implements Exception {
'NextcloudApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})'; 'NextcloudApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})';
} }
abstract class NextcloudAuthentication { class NextcloudHttpBasicAuthentication extends DynamiteAuthentication {
String get id;
Map<String, String> get headers;
}
class NextcloudHttpBasicAuthentication extends NextcloudAuthentication {
NextcloudHttpBasicAuthentication({ NextcloudHttpBasicAuthentication({
required this.username, required this.username,
required this.password, required this.password,
@ -100,63 +61,15 @@ class NextcloudHttpBasicAuthentication extends NextcloudAuthentication {
}; };
} }
class NextcloudClient { class NextcloudClient extends DynamiteClient {
NextcloudClient( NextcloudClient(
this.baseURL, { super.baseURL, {
final Map<String, String>? baseHeaders, super.baseHeaders,
final String? userAgent, super.userAgent,
final HttpClient? httpClient, super.httpClient,
this.cookieJar, super.cookieJar,
this.authentications = const [], super.authentications,
}) {
this.baseHeaders = {
...?baseHeaders,
};
this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent;
}
final String baseURL;
late final Map<String, String> baseHeaders;
late final HttpClient httpClient;
final CookieJar? cookieJar;
final List<NextcloudAuthentication> authentications;
Future<RawResponse> doRequest(
final String method,
final String path,
final Map<String, String> headers,
final Uint8List? body,
) async {
final uri = Uri.parse('$baseURL$path');
final request = await httpClient.openUrl(method, uri);
for (final header in {...baseHeaders, ...headers}.entries) {
request.headers.add(header.key, header.value);
}
if (body != null) {
request.add(body.toList());
}
if (cookieJar != null) {
request.cookies.addAll(await cookieJar!.loadForRequest(uri));
}
final response = await request.close();
if (cookieJar != null) {
await cookieJar!.saveFromResponse(uri, response.cookies);
}
final responseHeaders = <String, String>{};
response.headers.forEach((final name, final values) {
responseHeaders[name] = values.last;
}); });
return RawResponse(
response.statusCode,
responseHeaders,
await response.bodyBytes,
);
}
NextcloudCoreClient get core => NextcloudCoreClient(this); NextcloudCoreClient get core => NextcloudCoreClient(this);
NextcloudNewsClient get news => NextcloudNewsClient(this); NextcloudNewsClient get news => NextcloudNewsClient(this);

1
packages/nextcloud/pubspec.yaml

@ -8,7 +8,6 @@ environment:
dependencies: dependencies:
built_collection: ^5.1.1 built_collection: ^5.1.1
built_value: ^8.5.0 built_value: ^8.5.0
cookie_jar: ^4.0.2
crypto: ^3.0.3 crypto: ^3.0.3
crypton: ^2.0.5 crypton: ^2.0.5
dynamite_runtime: dynamite_runtime:

Loading…
Cancel
Save