Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.3.0 Required parameters #4

Merged
merged 4 commits into from
Oct 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions swagger_parser/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.3.0

- Add support for required annotations
- Fixed error with rest client parameters type in OpenApi v2

## 0.2.4

- Fixed error with '.' and ',' in url path
Expand Down
2 changes: 1 addition & 1 deletion swagger_parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ An example of YAML is shown below
### Configure package
```yaml
dev_dependencies:
swagger_parser: ^0.2.4
swagger_parser: ^0.3.0

swagger_parser:
json_path: assets/swagger.json # Required. Sets the json path directory for generated files
Expand Down
5 changes: 3 additions & 2 deletions swagger_parser/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class App extends StatefulWidget {

class _AppState extends State<App> {
@override
Widget build(BuildContext context) =>
const MaterialApp(home: Scaffold(body: SizedBox.shrink()));
Widget build(BuildContext context) => const MaterialApp(
home: Scaffold(body: SizedBox.shrink()),
);
}
8 changes: 4 additions & 4 deletions swagger_parser/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ dependencies:
dio: ^4.0.6
flutter:
sdk: flutter
freezed_annotation: ^2.1.0
freezed_annotation: ^2.2.0
json_annotation: ^4.7.0
retrofit: ^3.3.1

dev_dependencies:
build_runner: ^2.3.0
build_runner: ^2.3.2
carapacik_lints: ^1.2.2
freezed: ^2.1.1
json_serializable: ^6.5.1
freezed: ^2.2.0
json_serializable: ^6.5.3
retrofit_generator: ^4.2.0
swagger_parser:
path:
Expand Down
17 changes: 13 additions & 4 deletions swagger_parser/lib/src/generator/models/universal_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'programming_lang.dart';
class UniversalType {
const UniversalType({
required this.type,
this.isRequired = false,
this.isRequired = true,
this.arrayDepth = 0,
this.name,
this.jsonKey,
Expand All @@ -30,16 +30,25 @@ class UniversalType {
/// Object format
/// example: type = String, format = binary
final String? format;

int compareTo(UniversalType other) {
if (isRequired == other.isRequired) {
return 0;
} else if (isRequired) {
return -1;
}
return 1;
}
}

/// Converts [UniversalType] to type from specified language
extension SuitableType on UniversalType {
String byLang(ProgrammingLanguage lang) {
String byLang(ProgrammingLanguage lang, {bool isRequired = true}) {
switch (lang) {
case ProgrammingLanguage.dart:
return _dartType;
return _dartType + (isRequired ? '' : '?');
case ProgrammingLanguage.kotlin:
return _kotlinType;
return _kotlinType + (isRequired ? '' : '?');
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:collection/collection.dart';

import '../../utils/case_utils.dart';
import '../../utils/utils.dart';
import '../models/programming_lang.dart';
Expand All @@ -21,10 +23,14 @@ class $className with _\$$className {
''';
}

String _parametersToString(List<UniversalType> parameters) => parameters
.map(
(e) =>
'${e.jsonKey != null && e.name != e.jsonKey ? "\n @JsonKey(name: '${e.jsonKey}') " : '\n '}'
'required ${toSuitableType(e, ProgrammingLanguage.dart)} ${e.name},',
)
.join();
String _parametersToString(List<UniversalType> parameters) {
final sortedByRequired =
List<UniversalType>.from(parameters.sorted((a, b) => a.compareTo(b)));
return sortedByRequired
.map(
(e) =>
'${e.jsonKey != null && e.name != e.jsonKey ? "\n @JsonKey(name: '${e.jsonKey}') " : '\n '}'
'${e.isRequired ? 'required ' : ''}${toSuitableType(e, ProgrammingLanguage.dart, isRequired: e.isRequired)} ${e.name},',
)
.join();
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:collection/collection.dart';

import '../../utils/case_utils.dart';
import '../../utils/utils.dart';
import '../models/programming_lang.dart';
Expand Down Expand Up @@ -27,9 +29,14 @@ String _parametersInClass(List<UniversalType> parameters) => parameters
.map(
(e) =>
'${e.jsonKey != null && e.name != e.jsonKey ? "\n @JsonKey(name: '${e.jsonKey}')" : ''}\n'
' final ${toSuitableType(e, ProgrammingLanguage.dart)} ${e.name};',
' final ${toSuitableType(e, ProgrammingLanguage.dart, isRequired: e.isRequired)} ${e.name};',
)
.join();

String _parametersInConstructor(List<UniversalType> parameters) =>
parameters.map((e) => '\n required this.${e.name},').join();
String _parametersInConstructor(List<UniversalType> parameters) {
final sortedByRequired =
List<UniversalType>.from(parameters.sorted((a, b) => a.compareTo(b)));
return sortedByRequired
.map((e) => '\n ${e.isRequired ? 'required ' : ''}this.${e.name},')
.join();
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ String _toClientRequest(UniversalRequest request) {

String _toQueryParameter(UniversalRequestType parameter) =>
" @${parameter.parameterType.type}(${parameter.name != null ? "${parameter.parameterType.isPart ? 'name: ' : ''}'${parameter.name}'" : ''}) "
'required ${toSuitableType(parameter.type, ProgrammingLanguage.dart)} ${parameter.type.name!.toCamel},';
'${parameter.type.isRequired ? 'required ' : ''}${toSuitableType(parameter.type, ProgrammingLanguage.dart, isRequired: parameter.type.isRequired)} ${parameter.type.name!.toCamel},';
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ String _parameters(List<UniversalType> parameters) => parameters
.map(
(e) =>
'${e.jsonKey != null && e.name != e.jsonKey ? '\n @Json("${e.jsonKey}")' : ''}\n '
'var ${e.name}: ${toSuitableType(e, ProgrammingLanguage.kotlin)}',
'var ${e.name}: ${toSuitableType(e, ProgrammingLanguage.kotlin, isRequired: e.isRequired)}',
)
.join(',');
108 changes: 66 additions & 42 deletions swagger_parser/lib/src/parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import '../utils/case_utils.dart';
import 'parser_exception.dart';

// ignore_for_file: avoid_dynamic_calls
/// General class for parsing openApi json files into universal models
/// General class for parsing OpenApi json files into universal models
class OpenApiJsonParser {
OpenApiJsonParser(String jsonContent) {
_jsonContent = jsonDecode(jsonContent) as Map<String, dynamic>;
Expand Down Expand Up @@ -69,7 +69,7 @@ class OpenApiJsonParser {
final imports = SplayTreeSet<String>();
var isMultiPart = false;

/// Parses return type for client Query for openApi v3
/// Parses return type for client Query for OpenApi v3
UniversalType? returnTypeV3(Map<String, dynamic> map) {
if (!map.containsKey('200') ||
!(map['200'] as Map<String, dynamic>).containsKey(_contentVar)) {
Expand All @@ -84,20 +84,20 @@ class OpenApiJsonParser {
if ((contentType.value as Map<String, dynamic>).isEmpty) {
return null;
}
final parameter = _arrayWithDepth(
final typeWithImport = _arrayWithDepth(
contentType.value[_schemaVar] as Map<String, dynamic>,
);
if (parameter.import != null) {
imports.add(parameter.import!);
if (typeWithImport.import != null) {
imports.add(typeWithImport.import!);
}
return UniversalType(
type: parameter.type.type,
arrayDepth: parameter.type.arrayDepth,
type: typeWithImport.type.type,
arrayDepth: typeWithImport.type.arrayDepth,
);
}

/// Parses query parameters (parameters and requestBody)
/// into universal models for openApi v3
/// into universal models for OpenApi v3
List<UniversalRequestType> parametersV3(Map<String, dynamic> map) {
if (!map.containsKey(_parametersVar) &&
!map.containsKey(_requestBodyVar)) {
Expand All @@ -106,16 +106,23 @@ class OpenApiJsonParser {
final types = <UniversalRequestType>[];
if (map.containsKey(_parametersVar)) {
for (final rawParameter in map[_parametersVar] as List<dynamic>) {
final isRequired =
(rawParameter as Map<String, dynamic>)[_requiredVar] as bool?;
final typeWithImport = _arrayWithDepth(
rawParameter[_schemaVar] as Map<String, dynamic>,
name: rawParameter[_nameVar].toString(),
isRequired: isRequired ?? true,
);
if (typeWithImport.import != null) {
imports.add(typeWithImport.import!);
}
types.add(
UniversalRequestType(
parameterType: HttpParameterType.values.firstWhere(
(e) => e.name == (rawParameter[_inVar].toString()),
),
type: _arrayWithDepth(
rawParameter[_schemaVar] as Map<String, dynamic>,
name: rawParameter[_nameVar].toString(),
).type,
name: _checkForBody(rawParameter as Map<String, dynamic>)
type: typeWithImport.type,
name: _checkForBody(rawParameter)
? null
: rawParameter[_nameVar].toString(),
),
Expand Down Expand Up @@ -148,8 +155,10 @@ class OpenApiJsonParser {
if (isMultiPart) {
if ((contentType[_schemaVar] as Map<String, dynamic>)
.containsKey(_refVar)) {
final isRequired = map[_requestBodyVar][_requiredVar] as bool?;
final typeWithImport = _arrayWithDepth(
contentType[_schemaVar] as Map<String, dynamic>,
isRequired: isRequired ?? true,
);
final currentType = typeWithImport.type;
if (typeWithImport.import != null) {
Expand Down Expand Up @@ -196,8 +205,10 @@ class OpenApiJsonParser {
}
}
} else {
final isRequired = map[_requestBodyVar][_requiredVar] as bool?;
final typeWithImport = _arrayWithDepth(
contentType[_schemaVar] as Map<String, dynamic>,
isRequired: isRequired ?? true,
);
final currentType = typeWithImport.type;
if (typeWithImport.import != null) {
Expand All @@ -220,26 +231,25 @@ class OpenApiJsonParser {
return types;
}

/// Parses return type for client query for openApi v2
/// Parses return type for client query for OpenApi v2
UniversalType? returnTypeV2(Map<String, dynamic> map) {
if (!map.containsKey('200') ||
!(map['200'] as Map<String, dynamic>).containsKey(_schemaVar)) {
return null;
}
final parameter = _arrayWithDepth(
map['200'][_schemaVar] as Map<String, dynamic>,
);
if (parameter.import != null) {
imports.add(parameter.import!);
final typeWithImport =
_arrayWithDepth(map['200'][_schemaVar] as Map<String, dynamic>);
if (typeWithImport.import != null) {
imports.add(typeWithImport.import!);
}
return UniversalType(
type: parameter.type.type,
arrayDepth: parameter.type.arrayDepth,
type: typeWithImport.type.type,
arrayDepth: typeWithImport.type.arrayDepth,
);
}

/// Parses query parameters (parameters and requestBody)
/// into universal models for openApi v2
/// into universal models for OpenApi v2
List<UniversalRequestType> parametersV2(Map<String, dynamic> map) {
final types = <UniversalRequestType>[];
if (!map.containsKey(_parametersVar)) {
Expand All @@ -250,14 +260,22 @@ class OpenApiJsonParser {
isMultiPart = true;
}
for (final rawParameter in map[_parametersVar] as List<dynamic>) {
final isRequired =
(rawParameter as Map<String, dynamic>)[_requiredVar] as bool?;
final typeWithImport = _arrayWithDepth(
rawParameter,
name: rawParameter[_nameVar].toString(),
isRequired: isRequired ?? true,
useSchema: true,
);
if (typeWithImport.import != null) {
imports.add(typeWithImport.import!);
}
types.add(
UniversalRequestType(
parameterType: HttpParameterType.values
.firstWhere((e) => e.name == (rawParameter[_inVar].toString())),
type: _arrayWithDepth(
rawParameter as Map<String, dynamic>,
name: rawParameter[_nameVar].toString(),
).type,
type: typeWithImport.type,
name: _checkForBody(rawParameter)
? null
: rawParameter[_nameVar].toString(),
Expand All @@ -270,23 +288,19 @@ class OpenApiJsonParser {
(_jsonContent[_pathsVar] as Map<String, dynamic>)
.forEach((path, pathValue) {
(pathValue as Map<String, dynamic>).forEach((key, requestPath) {
final returnType = _version == OpenApiVersion.v2
? returnTypeV2(requestPath[_responsesVar] as Map<String, dynamic>)
: returnTypeV3(requestPath[_responsesVar] as Map<String, dynamic>);
final parameters = _version == OpenApiVersion.v2
? parametersV2(requestPath as Map<String, dynamic>)
: parametersV3(requestPath as Map<String, dynamic>);
final request = UniversalRequest(
isMultiPart: isMultiPart,
name: (key + path).toCamel,
requestType: HttpRequestType.fromString(key)!,
route: path,
returnType:
(_version == OpenApiVersion.v3_1 || _version == OpenApiVersion.v3)
? returnTypeV3(
requestPath[_responsesVar] as Map<String, dynamic>,
)
: returnTypeV2(
requestPath[_responsesVar] as Map<String, dynamic>,
),
parameters:
(_version == OpenApiVersion.v3_1 || _version == OpenApiVersion.v3)
? parametersV3(requestPath as Map<String, dynamic>)
: parametersV2(requestPath as Map<String, dynamic>),
isMultiPart: isMultiPart,
returnType: returnType,
parameters: parameters,
);
final currentTag = _getTag(requestPath);
final sameTagIndex =
Expand Down Expand Up @@ -410,6 +424,7 @@ class OpenApiJsonParser {
TypeWithImport _arrayWithDepth(
Map<String, dynamic> map, {
String? name,
bool useSchema = false,
bool isRequired = true,
}) {
if (map.containsKey(_typeVar) && map[_typeVar] == 'array') {
Expand All @@ -433,11 +448,20 @@ class OpenApiJsonParser {
format: map.containsKey(_formatVar) ? map[_formatVar].toString() : null,
type: map.containsKey(_typeVar)
? map[_typeVar].toString()
: _formatRef(map[_refVar].toString()),
: _formatRef(
useSchema
? map[_schemaVar][_refVar].toString()
: map[_refVar].toString(),
),
isRequired: isRequired,
),
import:
map.containsKey(_refVar) ? _formatRef(map[_refVar].toString()) : null,
import: map.containsKey(_typeVar)
? null
: _formatRef(
useSchema
? map[_schemaVar][_refVar].toString()
: map[_refVar].toString(),
),
);
}
}
Expand Down
Loading