Browse Source

feat(dynamite): Support multiple status codes with same schema

Signed-off-by: jld3103 <jld3103yt@gmail.com>
pull/715/head
jld3103 1 year ago
parent
commit
033e1088e9
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 206
      packages/dynamite/dynamite/lib/src/builder/client.dart

206
packages/dynamite/dynamite/lib/src/builder/client.dart

@ -8,6 +8,7 @@ import 'package:dynamite/src/helpers/dynamite.dart';
import 'package:dynamite/src/helpers/type_result.dart'; import 'package:dynamite/src/helpers/type_result.dart';
import 'package:dynamite/src/models/open_api.dart'; import 'package:dynamite/src/models/open_api.dart';
import 'package:dynamite/src/models/path_item.dart'; import 'package:dynamite/src/models/path_item.dart';
import 'package:dynamite/src/models/response.dart';
import 'package:dynamite/src/models/schema.dart'; import 'package:dynamite/src/models/schema.dart';
import 'package:dynamite/src/type_result/type_result.dart'; import 'package:dynamite/src/type_result/type_result.dart';
@ -297,13 +298,28 @@ Iterable<Method> buildTags(
b.annotations.add(refer('Deprecated').call([refer("''")])); b.annotations.add(refer('Deprecated').call([refer("''")]));
} }
final acceptHeader = operation.responses?.values var responses = <Response, List<int>>{};
.map((final response) => response.content?.keys) if (operation.responses != null) {
.whereNotNull() for (final responseEntry in operation.responses!.entries) {
.expand((final element) => element) final statusCode = int.parse(responseEntry.key);
.toSet() final response = responseEntry.value;
.join(',') ??
''; responses[response] ??= [];
responses[response]!.add(statusCode);
}
if (responses.length > 1) {
print('$operationId uses more than one response schema but we only generate the first one');
responses = Map.fromEntries([responses.entries.first]);
}
}
final acceptHeader = responses.keys
.map((final response) => response.content?.keys)
.whereNotNull()
.expand((final element) => element)
.toSet()
.join(',');
final code = StringBuffer(''' final code = StringBuffer('''
var _path = '${pathEntry.key}'; var _path = '${pathEntry.key}';
final _queryParameters = <String, dynamic>{}; final _queryParameters = <String, dynamic>{};
@ -497,111 +513,107 @@ final _response = await ${isRootClient ? 'this' : '_rootClient'}.doRequest(
''', ''',
); );
if (operation.responses != null) { for (final responseEntry in responses.entries) {
if (operation.responses!.length > 1) { final response = responseEntry.key;
throw Exception('Can not work with multiple status codes right now'); final statusCodes = responseEntry.value;
code.write(
'if (${statusCodes.map((final statusCode) => '_response.statusCode == $statusCode').join(' || ')}) {',
);
String? headersType;
String? headersValue;
if (response.headers != null) {
final identifier =
'${tag != null ? toDartName(tag, uppercaseFirstCharacter: true) : null}${toDartName(operationId, uppercaseFirstCharacter: true)}Headers';
final result = resolveObject(
spec,
state,
identifier,
Schema(
properties: response.headers!.map(
(final headerName, final value) => MapEntry(
headerName.toLowerCase(),
value.schema!,
),
),
),
isHeader: true,
);
headersType = result.name;
headersValue = result.deserialize('_response.responseHeaders');
} }
for (final responseEntry in operation.responses!.entries) {
final statusCode = responseEntry.key; String? dataType;
final response = responseEntry.value; String? dataValue;
code.write('if (_response.statusCode == $statusCode) {'); bool? dataNeedsAwait;
if (response.content != null) {
String? headersType; if (response.content!.length > 1) {
String? headersValue; throw Exception('Can not work with multiple mime types right now');
if (response.headers != null) { }
final identifier = for (final content in response.content!.entries) {
'${tag != null ? toDartName(tag, uppercaseFirstCharacter: true) : null}${toDartName(operationId, uppercaseFirstCharacter: true)}Headers'; final mimeType = content.key;
final result = resolveObject( final mediaType = content.value;
final result = resolveType(
spec, spec,
state, state,
identifier, toDartName(
Schema( '$operationId-response${responses.entries.length > 1 ? '-${responses.entries.toList().indexOf(responseEntry)}' : ''}-$mimeType',
properties: response.headers!.map( uppercaseFirstCharacter: true,
(final headerName, final value) => MapEntry(
headerName.toLowerCase(),
value.schema!,
),
),
), ),
isHeader: true, mediaType.schema!,
); );
headersType = result.name;
headersValue = result.deserialize('_response.responseHeaders');
}
String? dataType; if (mimeType == '*/*' || mimeType == 'application/octet-stream' || mimeType.startsWith('image/')) {
String? dataValue; dataType = 'Uint8List';
bool? dataNeedsAwait; dataValue = '_response.bodyBytes';
if (response.content != null) { dataNeedsAwait = true;
if (response.content!.length > 1) { } else if (mimeType.startsWith('text/') || mimeType == 'application/javascript') {
throw Exception('Can not work with multiple mime types right now'); dataType = 'String';
} dataValue = '_response.body';
for (final content in response.content!.entries) { dataNeedsAwait = true;
final mimeType = content.key; } else if (mimeType == 'application/json') {
final mediaType = content.value; dataType = result.name;
if (result.name == 'dynamic') {
final result = resolveType( dataValue = '';
spec, } else if (result.name == 'String') {
state,
toDartName(
'$operationId-response-$statusCode-$mimeType',
uppercaseFirstCharacter: true,
),
mediaType.schema!,
);
if (mimeType == '*/*' || mimeType == 'application/octet-stream' || mimeType.startsWith('image/')) {
dataType = 'Uint8List';
dataValue = '_response.bodyBytes';
dataNeedsAwait = true;
} else if (mimeType.startsWith('text/') || mimeType == 'application/javascript') {
dataType = 'String';
dataValue = '_response.body'; dataValue = '_response.body';
dataNeedsAwait = true; dataNeedsAwait = true;
} else if (mimeType == 'application/json') { } else if (result is TypeResultEnum || result is TypeResultBase) {
dataType = result.name; dataValue = result.deserialize(result.decode('await _response.body'));
if (result.name == 'dynamic') { dataNeedsAwait = false;
dataValue = '';
} else if (result.name == 'String') {
dataValue = '_response.body';
dataNeedsAwait = true;
} else if (result is TypeResultEnum || result is TypeResultBase) {
dataValue = result.deserialize(result.decode('await _response.body'));
dataNeedsAwait = false;
} else {
dataValue = result.deserialize('await _response.jsonBody');
dataNeedsAwait = false;
}
} else { } else {
throw Exception('Can not parse mime type "$mimeType"'); dataValue = result.deserialize('await _response.jsonBody');
dataNeedsAwait = false;
} }
} else {
throw Exception('Can not parse mime type "$mimeType"');
} }
} }
}
if (headersType != null && dataType != null) { if (headersType != null && dataType != null) {
b.returns = refer('Future<${state.classPrefix}Response<$dataType, $headersType>>'); b.returns = refer('Future<${state.classPrefix}Response<$dataType, $headersType>>');
code.write( code.write(
'return ${state.classPrefix}Response<$dataType, $headersType>(${dataNeedsAwait ?? false ? 'await ' : ''}$dataValue, $headersValue,);', 'return ${state.classPrefix}Response<$dataType, $headersType>(${dataNeedsAwait ?? false ? 'await ' : ''}$dataValue, $headersValue,);',
); );
} else if (headersType != null) { } else if (headersType != null) {
b.returns = refer('Future<$headersType>'); b.returns = refer('Future<$headersType>');
code.write('return $headersValue;'); code.write('return $headersValue;');
} else if (dataType != null) { } else if (dataType != null) {
b.returns = refer('Future<$dataType>'); b.returns = refer('Future<$dataType>');
code.write('return $dataValue;'); code.write('return $dataValue;');
} else { } else {
b.returns = refer('Future'); b.returns = refer('Future');
code.write('return;'); code.write('return;');
}
code.write('}');
} }
code.write(
'throw await ${state.classPrefix}ApiException.fromResponse(_response); // coverage:ignore-line\n', code.write('}');
);
} else {
b.returns = refer('Future');
} }
code.write(
'throw await ${state.classPrefix}ApiException.fromResponse(_response); // coverage:ignore-line\n',
);
b.body = Code(code.toString()); b.body = Code(code.toString());
}, },
); );

Loading…
Cancel
Save