diff --git a/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart b/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart index f78b6f0b..f1da8b3d 100644 --- a/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart @@ -175,9 +175,12 @@ String _toClientRequest( ..write(' $finalResponseType ') ..write('${request.name}('); - if (request.parameters.isNotEmpty || + final hasParameters = request.parameters.isNotEmpty || addExtrasParameter || - addDioOptionsParameter) { + addDioOptionsParameter || + request.configExtension.isCancelable; + + if (hasParameters) { sb.write('{\n'); } @@ -193,10 +196,11 @@ String _toClientRequest( if (addDioOptionsParameter) { sb.write(_addDioOptionsParameter()); } + if (request.configExtension.isCancelable) { + sb.write(_addDioCancelToken()); + } - if (request.parameters.isNotEmpty || - addExtrasParameter || - addDioOptionsParameter) { + if (hasParameters) { sb.write(' });\n'); } else { sb.write(');\n'); @@ -262,6 +266,9 @@ String _quoteJson(String value) => String _addDioOptionsParameter() => ' @DioOptions() RequestOptions? options,\n'; +String _addDioCancelToken() => + ' @CancelRequest() CancelToken? cancelToken,\n'; + String _toParameter(UniversalRequestType parameter, bool useMultipartFile) { var parameterType = parameter.type.toSuitableType( ProgrammingLanguage.dart, diff --git a/swagger_parser/lib/src/parser/model/universal_request.dart b/swagger_parser/lib/src/parser/model/universal_request.dart index ecd75677..7eaa6b0b 100644 --- a/swagger_parser/lib/src/parser/model/universal_request.dart +++ b/swagger_parser/lib/src/parser/model/universal_request.dart @@ -19,6 +19,7 @@ final class UniversalRequest { this.contentType = 'application/json', this.description, this.isDeprecated = false, + this.configExtension = const UniversalRequestConfigExtension(), }); /// Request name @@ -61,6 +62,8 @@ final class UniversalRequest { /// Value indicating whether this request is deprecated final bool isDeprecated; + final UniversalRequestConfigExtension configExtension; + @override bool operator ==(Object other) => identical(this, other) || @@ -139,3 +142,60 @@ enum HttpRequestType { static HttpRequestType? fromString(String type) => HttpRequestType.values.firstWhereOrNull((e) => e.name == type); } + +@immutable +final class UniversalRequestConfigExtension { + const UniversalRequestConfigExtension({ + bool? isCancelable, + }) : isCancelable = isCancelable ?? false; + + factory UniversalRequestConfigExtension.parse( + Map requestConfig, + ) { + final xDart = requestConfig[_xDartSection] as Map?; + return UniversalRequestConfigExtension( + isCancelable: bool.tryParse(xDart?[_isCancelableKey]?.toString() ?? ''), + ); + } + + static const _xDartSection = 'x-dart'; + + /// Whether or not the request should be cancelable. + /// + /// True if the `cancelable` flag in the `x-dart` section has been set to + /// `true` for the specific request. + /// + /// ## Example + /// + /// ```yaml + /// paths: + /// /path/variant4: + /// get: + /// x-dart: + /// cancelable: true + /// tags: + /// - sse + /// responses: + /// 200: + /// content: + /// application/octect-stream: + /// schema: + /// type: integer + /// format: binary + /// ``` + final bool isCancelable; + static const _isCancelableKey = 'cancelable'; + + @override + int get hashCode => isCancelable.hashCode; + + @override + bool operator ==(Object other) => + other is UniversalRequestConfigExtension && + other.isCancelable == isCancelable; + + @override + String toString() => 'UniversalRequestConfigExtension(' + 'isCancelable: $isCancelable' + ')'; +} diff --git a/swagger_parser/lib/src/parser/parser/open_api_parser.dart b/swagger_parser/lib/src/parser/parser/open_api_parser.dart index 2a81bb9e..537f6a39 100644 --- a/swagger_parser/lib/src/parser/parser/open_api_parser.dart +++ b/swagger_parser/lib/src/parser/parser/open_api_parser.dart @@ -709,6 +709,7 @@ class OpenApiParser { parameters: parameters, isDeprecated: requestPath[_deprecatedConst].toString().toBool() ?? false, + configExtension: UniversalRequestConfigExtension.parse(requestPath), ); // we are converting the tag to the snake case // later tag is used to determine the file name