diff --git a/api_automatic/CHANGELOG.md b/api_automatic/CHANGELOG.md
new file mode 100644
index 0000000..05f16b8
--- /dev/null
+++ b/api_automatic/CHANGELOG.md
@@ -0,0 +1,488 @@
+# 2.2.3
+
+* Fixed Issue ([#138](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/138))
+* Fixed Issue ([#269](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/269))
+* Fixed generation of fields with type int32, int64. Parsing it like int
+
+* Fixed Issue ([#265](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/265))
+* Fixed generation of responses and request bodies in separate file
+
+# 2.2.1
+
+* Added ability to generated models to separate file
+* **BREAKING** Removed generation of client_index if generate only models
+* Fixed Issue ([#244](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/244))
+
+# 2.2.0+1
+
+* Updated changelog (see previous version changes)
+
+# 2.2.0
+
+* **BREAKING** Upgraded to support json_serializable 5.0.0
+
+# 2.1.3+2
+
+* Fixed Issue ([#245](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/245))
+* Fixed ability to set exclude_path and include_path
+
+# 2.1.3+1
+
+* Fixed Issue ([#248](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/248))
+* Fix cases when responses was named like numbers
+
+# 2.1.3
+
+* Fixed cases when swagger has not put post get requests
+* Added validation for requests names generation
+
+# 2.1.2
+
+* Updated packages json_serializable, json_annotation, build_runner
+
+# 2.1.1+4
+
+* Fix for default value for named parameters
+
+# 2.1.1+3
+
+* Fixed Issue ([#240](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/240))
+* Fixed Issue ([#211](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/211))
+* Fixed cases when parameters named by keywords, for example In, For, Class etx
+* Added generation of parameters from, path (not only from requests)
+
+# 2.1.1+2
+
+* Fixed issues when content has no application/json child
+
+# 2.1.1+1
+
+* Fixed Issue ([#235](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/235))
+* Fixed cases when field number 'number' generated as $num
+* Fixed cases when field 'num' generated ad 'num' (basic dart type)
+
+# 2.1.1
+
+* Stabilized generator
+* Fixed issue when parameters named like int, double etc.
+* Fixed Issue ([#108](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/108))
+
+# 2.1.0-prerelease.9
+
+* Fixed Issue ([#228](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/228))
+* Fixed Issue ([#206](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/206))
+* Fixed cases when file names like some_file.extension.swagger.json.dart.json
+* Removed generation of converter when build_only_models is true
+
+
+# 2.1.0-prerelease.8
+
+* Fixed Issue ([#221](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/221))
+* Added generation of int get hashCode
+* Added example
+
+# 2.1.0-prerelease.7
+
+* Fixed Issue ([#186](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/186))
+* Fixed Issue ([#204](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/204))
+
+# 2.1.0-prerelease.6
+
+* **BREAKING**: Added dollar signs to generated converter and mappings
+
+# 2.1.0-prerelease.5
+
+* Fixed Issue ([#212](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/212))
+* Fixed border cases with parameters with duplicated names (for ex 'book' and 'book[]')
+* Fixed cases when Parameters contains forbidden characters
+
+# 2.1.0-prerelease.4
+
+* Fixed Issue ([#208](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/208))
+* Fixed cases with dashes in request named
+* Fixed models from responses names generation
+
+# 2.1.0-prerelease.3
+
+* **BREAKING**: includeIfNull now just bool? value. Needs update of build.yaml if this feature used
+
+# 2.1.0-prerelease.2
+
+* Fixed Issue ([#201](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/201))
+
+* Fixed Issue ([#202](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/202))
+
+* Added support .json files instead .swagger (.swagger are supported too)
+
+* Fixed errors when models has symbols, dots, numbers...
+
+
+# 2.1.0-prerelease.1
+
+* Fully refactored requests generator
+
+# 2.0.8+1
+
+* Fixed Issue ([#187](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/187)) It's about request parameters named "client"
+
+* Fixed Issue ([#188](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/188)) It's about isses with enum names generation.
+
+# 2.0.8
+
+* Fix case when enum in model has name with underscores.
+* Updated logo design
+
+# 2.0.7+1
+
+* Fixed Issue ([#190](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/190))
+* Fixed case when request does not have type specified. Made it Object.
+
+# 2.0.7
+
+* Fixed models generator in cases of List of Lists of Lists of... of some type
+* Formatted code
+
+# 2.0.6+1
+
+* Fixed Issue ([#72](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/72))
+
+# 2.0.6
+
+* Fixed Issue ([#163](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/163))
+* Updated logo design
+
+# 2.0.5+2
+
+* Fixed issue with list of enums in request parameter
+
+# 2.0.5
+
+* Added new generator_options
+
+# 2.0.4
+
+* Added equals override method to all Models
+
+# 2.0.3
+
+* Removed meta dependency
+
+# 2.0.2
+
+* Fixed meta version to 1.3.0
+
+# 2.0.1
+
+* Updated dependencies
+* Added possibility to made postfix for models
+
+# 2.0.0-nullsafety.9
+
+* Removed ..RemoveWhere spike on generated models
+
+# 2.0.0-nullsafety.8
+
+* Fixed Issues #167 and #168
+
+# 2.0.0-nullsafety.7+2
+
+* Fixed critical error
+
+# 2.0.0-nullsafety.7+1
+
+* Made header default values not sensative
+
+# 2.0.0-nullsafety.7
+
+* Added build option to set default values for headers
+
+# 2.0.0-nullsafety.6
+
+* Made ALL models parameter not required
+
+# 2.0.0-nullsafety.5
+
+* Fixed generation of Lists of Strings for models
+
+# 2.0.0-nullsafety.4
+
+* Fixed issues with null-safety
+
+# 2.0.0-nullsafety.3+3
+
+* Fixed analyser issues
+
+# 2.0.0-nullsafety.3+2
+
+* Updated documentation
+
+# 2.0.0-nullsafety.3+1
+
+* Updated dependencies
+
+# 2.0.0-nullsafety.3
+
+* Implemented generation of models from responses injected
+
+# 2.0.0-nullsafety.2+1
+
+* Improve documentation
+
+# 2.0.0-nullsafety.2
+
+* Made generated enums not nullable
+
+# 2.0.0-nullsafety.1
+
+* Removed nullable from fields with default values
+
+# 2.0.0-nullsafety.0
+
+* Added support for null safety
+
+# 1.7.1
+
+* Generate models for 201 HTTP Responses too
+
+# 1.7.0
+
+* Added support of requestBody field for POST requests
+
+# 1.6.8
+
+* Fixed issue with usage of KEY instead of NAME on defined parametets
+
+# 1.6.7
+
+* Fixed issue with basic types in array elements
+
+# 1.6.6+2
+
+* Added null-check for _formatDate method
+
+# 1.6.6+1
+
+* Removed dependency to intl
+* Removed support of template of date
+* Setted Date parsing to yyyy-MM-dd
+
+# 1.6.6
+
+* Added generation of custom Date to json mapping.
+* Added build parameter with Date format date_formatter (String)
+
+# 1.6.5+2
+
+* Hotfix for body generation
+
+# 1.6.5+1
+
+* Hotfix of using meta
+
+# 1.6.5
+
+* Fix issue with requestBody parameter. It was not used, currently it adds 'body' parameter to requests
+
+# 1.6.4
+
+* Added support of default value per item for bool properties. For ex. "name": bool, "defalut": true => defaultValue: true
+
+# 1.6.3
+
+* Fixed issue with allOf exception
+
+# 1.6.2
+
+* Fixed issue with datetime in refs
+
+# 1.6.1
+
+* Fixed issue with enums in definitions and Date time
+
+# 1.6.0
+
+* Added new build option use_inheritance to enable/disable inheritance support for v3
+* Fixed issue with basic types (String, int...) used as definitions
+
+# 1.5.1
+
+* Added 'export file_name.swagger.enums.dart' to main generated file
+
+# 1.5.0
+
+* Fixed issue with pre-defined parameters on V3 version
+
+# 1.4.9
+
+* Fixed issue with Lists of enums in definitions
+* Fixed issue with defined parameters on v2
+
+# 1.4.8
+
+* Introduced new flag to manage @required attribute of Headers
+
+# 1.4.7
+
+* Fixed Issue ([#102](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/102))
+
+# 1.4.6
+
+* Added generation of copyWith method for models
+
+# 1.4.5
+
+* Fixed Issue ([#99](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/99))
+* **BREAKING**: Fixed enums naming. Enums with _ are replaced by PascalCase. For example, Response_type replaced by ResponseType.
+
+# 1.4.4
+
+* Fixed issue with build_only_models flag
+* **BREAKING**: fix misspelling with `overridden` word. If you use it, please add additional `d`.
+
+# 1.4.3
+
+* Fixed error with ref in allOf and bool values in enums
+
+# 1.4.2
+
+* Fixed issue with adding responses to JsonSerializableConverter mapping
+
+# 1.4.1
+
+* Fixed issue with enum names in requests
+* Fixed reusable Components - Parameters map
+
+# 1.4.0
+
+* Added support of int in request fields and models fields (Previously was only integer)
+
+# 1.3.9
+
+* Added ignoring of request parameters with empty IN parameter
+
+# 1.3.8
+
+* Added includeIfEmpty option to build options
+* Added support of requestBody parameter (And enums as requestBody parameter)
+* Fixed some minor bugs
+
+# 1.3.7
+
+* Fixed case when empty Enums generated from models
+
+# 1.3.6
+
+* Removed generation of empty Enums files
+
+# 1.3.5
+
+* Fixed commas in request parameters
+* Removed defaultValue property for generated Lists of Enums
+* Added new flag use_path_for_request_names. Read README to learn more about it
+* Fixed extends+ClassName structure for Swagger v3
+
+# 1.3.4
+
+* Fixed not valid strings in FromJson method
+
+# 1.3.3
+
+* Added new property to build config named enums_case_sensitive
+
+# 1.3.2
+
+* Fixed issue when parsing List of Enums
+
+# 1.3.0
+
+# 1.3.1
+
+* Code refactoring
+* Removed swaggerGeneratedUnknown for Enums
+
+# 1.3.0
+
+* Fixed Issue ([#68](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/68))
+
+# 1.2.2
+
+* Fixed enums names
+
+# 1.2.1
+
+* Added sorting of imports and exports in alphabetical order
+
+# 1.2.0
+
+* Enums become being generated in separate file
+* Fixed Issue ([#58](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/58))
+* Fixed some bugs
+
+## 1.1.0
+
+* Fixed issues with Enums usage
+* Fixed issues with enum naming name
+* Fixed some bugs
+
+## 1.0.10
+
+* Fixed issue with enums in request bodies
+
+## 1.0.9
+
+* Implemented possibility to have enums in request body
+
+## 1.0.8
+
+* Fixed not standard request parameter Type names
+* Added output message in case of formatting error
+
+## 1.0.7
+
+* Fixed a lot of issues with Enums in request parameters
+* Changed naming approach for Enums in request parameters
+* Fixed issue with key words in Enum/Model names
+
+## 1.0.6
+
+* Added support of unknownEnumValue: MyClass.swaggerGeneratedUnknown
+
+## 1.0.5
+
+* Added usage of auto formatting code
+
+## 1.0.4
+
+* Fixed build error on Example
+* Removed empty lines in pubspec.yaml
+* Added defined type to generated converters
+
+## 1.0.3
+
+* Remove unnecessary braces
+* Fixed client_index.dart file
+
+## 1.0.2
+
+* Implemented inheritance support. Models can extend others.
+* Fixed bug with build_only_models flag
+* Added missing tests for models_generator
+
+## 1.0.1
+
+* Fixed bug with request parameter and result type, when schema.ref used
+* Added real example of usage with Pet Store
+
+## 1.0.0+2
+
+* Fix score on pub.dev
+
+## 1.0.0+1
+
+* Add more info to readme
+* Fix warnings
+* Add code coverage(codecov)
+
+## 1.0.0
+
+* First release
diff --git a/api_automatic/LICENSE b/api_automatic/LICENSE
new file mode 100644
index 0000000..c9a6960
--- /dev/null
+++ b/api_automatic/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020 EPAM Systems, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/api_automatic/README.md b/api_automatic/README.md
new file mode 100644
index 0000000..fab19b5
--- /dev/null
+++ b/api_automatic/README.md
@@ -0,0 +1,153 @@
+
+
+
+
+Code partially generated with [chopper](https://pub.dev/packages/chopper)
+
+# :mega: **Build dart types from Swagger/OpenAPI schemas**
+
+[](https://pub.dartlang.org/packages/swagger_dart_code_generator)
+
+
+
+
+[](https://codecov.io/gh/epam-cross-platform-lab/swagger-dart-code-generator)
+
+
+SwaggerDartCodeGenerator is a code generator that looks for `*.swagger` files and builds `.swagger.dart` files, based on the schema. Code generation based on Chopper and JsonAnnotation models and can be configured for your needs.
+
+---
+
+## **Overview**
+In general case for each .swagger file three outputs will be created.
+.dart generated by Swagger dart code generator, contains all models, requests, converters, etc.
+[Since v1.2.0] .enums.dart generated by Swagger dart code generator, contains all enums and enums mappings.
+.chopper.dart - generated by chopper.
+.g.dart - generated by json_serializable.
+
+
+
+## **Installation**
+The generated code uses the following packages in run-time:
+```yaml
+dependencies:
+ chopper: ^4.0.1
+ json_annotation: ^4.1.0
+```
+
+Add the following to your `pubspec.yaml` file to be able to do code generation:
+```yaml
+dev_dependencies:
+ build_runner: ^2.1.4
+ chopper_generator: ^4.0.2
+ json_serializable: ^5.0.0
+ swagger_dart_code_generator: any
+```
+
+Then run:
+```shell
+pub packages get
+```
+or
+```shell
+flutter packages get
+```
+
+Now SwaggerGenerator will generate the API files for you by running:
+```shell
+pub run build_runner build
+```
+or
+```shell
+flutter pub run build_runner build
+```
+
+## **Configuration**
+Swagger generator offers some configuration options to generate code. All options should be included on `build.yaml` file on the root of the project:
+
+```yaml
+targets:
+ $default:
+ builders:
+ swagger_dart_code_generator:
+ options:
+ # custom configuration options!
+```
+
+| Option |Default value | Is required | Description |
+| - | - | - | - |
+| `use_inheritance` | `true` | `false` | Enables and disables extends keyword. |
+| `with_base_url` | `true` | `false` | If this option is false, generator will ignore base url in swagger file. |
+| `use_required_attribute_for_headers` | `true` | `false` | If this option is false, generator will not add @required attribute to headers. |
+| `with_converter` | `true` | `false` | If option is true, combination of all mappings will be generated. |
+| `ignore_headers` | `false` | `false` | If option is true, headers will not be generated. |
+| `enums_case_sensitive` | `true` | `false` | If value is false, 'enumValue' will be defined like Enum.enumValue even it's json key equals 'ENUMVALUE' |
+| `include_paths` | `[]` | `false` | List of Regex If not empty - includes only paths matching reges |
+| `exclude_paths` | `[]` | `false` | List of Regex If not empty -exclude paths matching reges |
+| `use_default_null_for_lists` | `false` | `false` | If option is true, default value for lists will be null, otherwise - [] |
+| `build_only_models` | `false` | `false` | If option is true, chopper classes will not be generated. |
+| `separate_models` | `false` | `false` | If option true, generates models into separate file. |
+| `include_if_null` | `null` | `false` | Sets includeIfNull JsonAnnotation feature and sets value for it. If null - not set anything. |
+| `default_values_map` | `[]` | `false` | Contains map of types and theirs default values. See [DefaultValueMap](#default-value-map-for-model-generation). |
+| `response_override_value_map` | `[]` | `false` | Contains map of responses and theirs overridden values. See [ResponseOverrideValueMap](#response-override-value-map-for-requests-generation). |
+| `input_folder` | `-` | `true` | Path to folder with .swagger files (for ex. swagger_examples, or lib/swaggers). |
+| `output_folder` | `-` | `true` | Path to output folder (for ex. lib/generated). |
+
+It's important to remember that, by default, [build](https://github.com/dart-lang/build) will follow [Dart's package layout conventions](https://dart.dev/tools/pub/package-layout), meaning that only some folders will be considered to parse the input files. So, if you want to reference files from a folder other than `lib/`, make sure you've included it on `sources`:
+
+```yaml
+targets:
+ $default:
+ sources:
+ - lib/**
+ - swagger_examples/**
+ - swaggers/**
+```
+
+### **Default Value Map for model generation**
+
+If you want to add defaultValue: attribute to fields with concrete type you can use default value map. Please see next example:
+
+```yaml
+targets:
+ $default:
+ builders:
+ swagger_dart_code_generator:
+ options:
+ input_folder: 'lib/swaggers'
+ output_folder: 'lib/generated_code/'
+ default_values_map:
+ - type_name: int
+ default_value: '36'
+ - type_name: String
+ default_value: 'default'
+ - type_name: 'List'
+ default_value: '[]'
+ exclude_paths:
+ - '\/cars\/get'
+ include_paths:
+ - '\/popular\/cars'
+```
+
+### **Response Override Value Map for requests generation**
+
+If you want to override response for concrete request, you can use response_override_value_map. For example:
+
+```yaml
+targets:
+ $default:
+ builders:
+ swagger_dart_code_generator:
+ options:
+ input_folder: 'lib/swaggers'
+ output_folder: 'lib/generated_code/'
+ response_override_value_map:
+ - url: '/store/inventory'
+ method: get
+ overridden_value: 'List'
+ - url: '/news/latest'
+ method: put
+ overridden_value: 'MyPerfectType'
+```
+
+Check the [examples](https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/tree/master/example) to see how to use it in details.
diff --git a/api_automatic/analysis_options.yaml b/api_automatic/analysis_options.yaml
new file mode 100644
index 0000000..b429b96
--- /dev/null
+++ b/api_automatic/analysis_options.yaml
@@ -0,0 +1,15 @@
+# https://www.dartlang.org/guides/language/analysis-options
+
+include: package:pedantic/analysis_options.yaml
+
+analyzer:
+ strong-mode:
+ implicit-casts: false
+ exclude:
+ - example/**/*.dart
+ - lib/**/*.g2.dart
+linter:
+ rules:
+ - type_annotate_public_apis
+ - void_checks
+ - unnecessary_new
\ No newline at end of file
diff --git a/api_automatic/assets/lib_full_logo.png b/api_automatic/assets/lib_full_logo.png
new file mode 100644
index 0000000..e34b7b7
Binary files /dev/null and b/api_automatic/assets/lib_full_logo.png differ
diff --git a/api_automatic/assets/lib_logo.png b/api_automatic/assets/lib_logo.png
new file mode 100644
index 0000000..162b25a
Binary files /dev/null and b/api_automatic/assets/lib_logo.png differ
diff --git a/api_automatic/assets/overview_image.png b/api_automatic/assets/overview_image.png
new file mode 100644
index 0000000..a5e8479
Binary files /dev/null and b/api_automatic/assets/overview_image.png differ
diff --git a/api_automatic/build.yaml b/api_automatic/build.yaml
new file mode 100644
index 0000000..feca356
--- /dev/null
+++ b/api_automatic/build.yaml
@@ -0,0 +1,14 @@
+targets:
+ swagger_dart_code_generator:swagger_dart_code_generator:
+ builders:
+ swagger_dart_code_generator:
+ enabled: True
+builders:
+ swagger_dart_code_generator:
+ import: "package:swagger_dart_code_generator/swagger_dart_code_generator.dart"
+ builder_factories: ["swaggerCodeBuilder"]
+ build_extensions:
+ "$lib$": [".swagger.dart", ".models.dart", ".converter.dart"]
+ build_to: source
+ auto_apply: dependents
+ runs_before: [ "json_serializable"]
diff --git a/api_automatic/lib/src/code_generators/constants.dart b/api_automatic/lib/src/code_generators/constants.dart
new file mode 100644
index 0000000..367ac77
--- /dev/null
+++ b/api_automatic/lib/src/code_generators/constants.dart
@@ -0,0 +1,67 @@
+const List successResponseCodes = [
+ '200',
+ '201',
+];
+
+const List kKeyClasses = ['Response', 'Request'];
+const kBasicTypes = [
+ 'string',
+ 'int',
+ 'integer',
+ 'double',
+ 'float',
+ 'bool',
+ 'boolean',
+ 'num',
+];
+
+const kChopperService = 'ChopperService';
+const kRetrofitApi = 'RestApi';
+const kResponse = 'Response';
+const kFutureResponse = 'Future';
+const kString = 'string';
+const kUndefinedParameter = 'undefinedParameter';
+
+const kResponses = '/responses/';
+
+//Request types
+const kPath = 'path';
+const kOptionalBody = 'optionalBody';
+const kFormData = 'formData';
+
+const kDefaultBodyParameter = 'Object';
+const kField = 'Field';
+const kRequestTypeOptions = 'options';
+
+const successDescriptions = ['Success', 'OK', 'default response'];
+
+const kBasicTypesMap = {
+ 'integer': 'int',
+ 'int': 'int',
+ 'int32': 'int',
+ 'int64': 'int',
+ 'boolean': 'bool',
+ 'bool': 'bool',
+ 'string': 'String',
+ 'file': 'List',
+ 'number': 'num',
+ 'object': 'Object',
+};
+
+const kObject = 'object';
+const kBinary = 'binary';
+const kHeader = 'header';
+const kCookie = 'cookie';
+const kArray = 'array';
+const kEnum = 'enum';
+const kBody = 'body';
+
+const kDynamic = 'dynamic';
+
+const supportedRequestTypes = ['get', 'post', 'put', 'delete', 'head', 'patch'];
+
+const kServiceHeader = '''
+// **************************************************************************
+// The file is generated automatically. Do not edit files
+// **************************************************************************
+ ''';
diff --git a/api_automatic/lib/src/code_generators/swagger_additions_generator.dart b/api_automatic/lib/src/code_generators/swagger_additions_generator.dart
new file mode 100644
index 0000000..3693f45
--- /dev/null
+++ b/api_automatic/lib/src/code_generators/swagger_additions_generator.dart
@@ -0,0 +1,225 @@
+import 'package:swagger_dart_code_generator/src/definitions.dart';
+import 'package:recase/recase.dart';
+import 'package:swagger_dart_code_generator/src/extensions/file_name_extensions.dart';
+import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
+
+///Generates index file content, converter and additional methods
+class SwaggerAdditionsGenerator {
+ static const mappingVariableName = 'generatedMapping';
+
+ ///Generates index.dart for all generated services
+ String generateIndexes(Map> buildExtensions) {
+ final importsList = buildExtensions.keys.map((String key) {
+ final fileName = key.split('/').last.replaceAll('-', '_').replaceAll('.json', '.swagger');
+ final className = getClassNameFromFileName(key.split('/').last);
+
+ return 'export \'$fileName.dart\' show $className;';
+ }).toList();
+
+ importsList.sort();
+
+ return importsList.join('\n');
+ }
+
+ ///Generated Map of all models generated by generator
+ String generateConverterMappings(
+ Map> buildExtensions, bool hasModels, GeneratorOptions options) {
+ if (!hasModels) {
+ return '';
+ }
+
+ final maps = StringBuffer();
+ final imports = [];
+ buildExtensions.keys.forEach((String key) {
+ final className = "${getClassNameFromFileName(key.split('/').last)}$converterClassEnding";
+
+ final fileName = getFileNameBase(className);
+ maps.writeln(' ...$className,');
+ imports.add("import '$fileName.swagger.dart';");
+ });
+
+ imports.sort();
+
+ final mapping =
+ '''
+${imports.join('\n')}
+
+final Map)> $mappingVariableName = {
+$maps};
+''';
+
+ return mapping;
+ }
+
+ ///Generated imports for concrete service
+ String generateImportsContent(
+ String swaggerFileName,
+ bool hasModels,
+ bool buildOnlyModels,
+ bool hasEnums,
+ bool separateModels,
+ List customModelPath,
+ ) {
+ final result = StringBuffer();
+
+ final chopperPartImport = buildOnlyModels ? '' : "part '$swaggerFileName.g.dart';";
+
+ final chopperImports =
+ buildOnlyModels ? '' : '''import 'package:dio/dio.dart';
+import 'package:retrofit/retrofit.dart';''';
+
+ final enumsImport = hasEnums ? "import '${swaggerFileName}_enums.dart';" : '';
+
+ final enumsExport = hasEnums ? "export '${swaggerFileName}_enums.dart';" : '';
+
+ if (hasModels && !separateModels) {
+ result.writeln(
+ """
+import 'package:json_annotation/json_annotation.dart';
+import 'package:collection/collection.dart';
+""");
+ }
+
+ if (customModelPath.isNotEmpty) {
+ for (var item in customModelPath) {
+ result.write("import '$item';");
+ }
+ }
+
+ if (hasModels && separateModels) {
+ result.write("import '${swaggerFileName}_models.dart';");
+ }
+
+ if (chopperImports.isNotEmpty) {
+ result.write(chopperImports);
+ }
+ if (enumsImport.isNotEmpty) {
+ result.write(enumsImport);
+ }
+
+ if (enumsExport.isNotEmpty) {
+ result.write(enumsExport);
+ }
+
+ if (hasModels && separateModels) {
+ result.write("export '${swaggerFileName}_models.dart';");
+ }
+
+ result.write('\n\n');
+
+ if (chopperPartImport.isNotEmpty) {
+ result.write(chopperPartImport);
+ }
+ if (hasModels && !separateModels) {
+ result.write("part '$swaggerFileName.swagger.g.dart';");
+ }
+
+ return result.toString();
+ }
+
+ ///Additional method to convert date to json
+ String generateDateToJson() {
+ return '''
+// ignore: unused_element
+String? _dateToJson(DateTime? date) {
+ if(date == null)
+ {
+ return null;
+ }
+
+ final year = date.year.toString();
+ final month = date.month < 10 ? '0\${date.month}' : date.month.toString();
+ final day = date.day < 10 ? '0\${date.day}' : date.day.toString();
+
+ return '\$year-\$month-\$day';
+ }
+''';
+ }
+
+ ///Copy-pasted converter from internet
+ String generateCustomJsonConverter(String fileName, GeneratorOptions options) {
+ if (!options.withConverter) {
+ return '';
+ }
+ return '''
+typedef \$JsonFactory = T Function(Map json);
+
+class \$CustomJsonDecoder {
+ \$CustomJsonDecoder(this.factories);
+
+ final Map factories;
+
+ dynamic decode(dynamic entity) {
+ if (entity is Iterable) {
+ return _decodeList(entity);
+ }
+
+ if (entity is T) {
+ return entity;
+ }
+
+ if (entity is Map) {
+ return _decodeMap(entity);
+ }
+
+ return entity;
+ }
+
+ T _decodeMap(Map values) {
+ final jsonFactory = factories[T];
+ if (jsonFactory == null || jsonFactory is! \$JsonFactory) {
+ return throw "Could not find factory for type \$T. Is '\$T: \$T.fromJsonFactory' included in the CustomJsonDecoder instance creation in bootstrapper.dart?";
+ }
+
+ return jsonFactory(values);
+ }
+
+ List _decodeList(Iterable values) =>
+ values.where((v) => v != null).map((v) => decode(v) as T).toList();
+}
+
+class \$JsonSerializableConverter extends chopper.JsonConverter {
+ @override
+ chopper.Response convertResponse(chopper.Response response) {
+ if (response.bodyString.isEmpty) {
+ // In rare cases, when let's say 204 (no content) is returned -
+ // we cannot decode the missing json with the result type specified
+ return chopper.Response(response.base, null, error: response.error);
+ }
+
+ final jsonRes = super.convertResponse(response);
+ return jsonRes.copyWith(
+ body: \$jsonDecoder.decode(jsonRes.body) as ResultType);
+ }
+}
+
+final \$jsonDecoder = \$CustomJsonDecoder(${fileName.pascalCase}JsonDecoderMappings);
+ ''';
+ }
+
+ static String getClientContent(
+ String className,
+ String host,
+ String basePath,
+ GeneratorOptions options,
+ ) {
+ final baseUrlString = options.withBaseUrl ? "baseUrl: 'https://$host$basePath'" : '/*baseUrl: YOUR_BASE_URL*/';
+
+ final converterString =
+ options.withConverter ? 'converter: \$JsonSerializableConverter(),' : 'converter: chopper.JsonConverter(),';
+
+ final chopperClientBody =
+ '''
+ if(client!=null){
+ return _\$$className(client);
+ }
+
+ final newClient = ChopperClient(
+ services: [_\$$className()],
+ $converterString
+ $baseUrlString);
+ return _\$$className(newClient);
+''';
+ return chopperClientBody;
+ }
+}
diff --git a/api_automatic/lib/src/code_generators/swagger_converter_generator.dart b/api_automatic/lib/src/code_generators/swagger_converter_generator.dart
new file mode 100644
index 0000000..ea1561e
--- /dev/null
+++ b/api_automatic/lib/src/code_generators/swagger_converter_generator.dart
@@ -0,0 +1,96 @@
+import 'dart:convert';
+import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
+import 'package:swagger_dart_code_generator/src/definitions.dart';
+import 'package:swagger_dart_code_generator/src/extensions/string_extension.dart';
+import 'package:recase/recase.dart';
+import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
+import 'constants.dart';
+
+class SwaggerConverterGenerator {
+ String generate(String dartCode, String fileName, GeneratorOptions options) {
+ return '';
+
+ return '''
+final Map)> ${fileName.pascalCase}$converterClassEnding =
+{
+${_generateModelsMapping(dartCode, options)}};''';
+ }
+
+ String _generateModelsMapping(String dartCode, GeneratorOptions options) {
+ final result = [];
+ final dynamic map = jsonDecode(dartCode);
+
+ final classes = getDefinitions(map);
+
+ final classesFromResponses = SwaggerModelsGenerator.getClassesFromResponses(dartCode, options);
+
+ classes.addAll(classesFromResponses);
+
+ if (classes.isNotEmpty) {
+ for (var i = 0; i < classes.keys.length; i++) {
+ final key = classes.keys.elementAt(i).toString();
+
+ final definition = classes[key];
+
+ if (definition['enum'] != null) {
+ continue;
+ }
+
+ if (kBasicTypes.contains(definition['type'].toString().toLowerCase())) {
+ continue;
+ }
+
+ if (definition['type'] == 'array' && definition['items'] != null && definition['items']['type'] == 'enum') {
+ continue;
+ }
+
+ final validatedName = SwaggerModelsGenerator.getValidatedClassName(key) + options.modelPostfix;
+
+ result.add('\t$validatedName: $validatedName.fromJsonFactory,');
+ }
+ }
+
+ final responses = getResponses(map);
+ if (responses.isNotEmpty) {
+ responses.keys.forEach((key) {
+ if (!result.contains(key)) {
+ final response = responses[key] as Map?;
+
+ final content = response == null ? null : response['content'] as Map?;
+
+ final firstContent =
+ content == null || content.entries.isEmpty ? null : content.entries.first.value as Map?;
+
+ final schema = firstContent == null ? null : firstContent['schema'] as Map?;
+
+ if (schema != null && content!.entries.length == 1 && !schema.containsKey('\$ref')) {
+ final validatedName = SwaggerModelsGenerator.getValidatedClassName(key.capitalize + options.modelPostfix);
+ result.add('\t$validatedName: $validatedName.fromJsonFactory,');
+ }
+ }
+ });
+ }
+
+ return result.join('\n');
+ }
+
+ Map getDefinitions(dynamic map) {
+ if (map['definitions'] != null) {
+ return map['definitions'] as Map? ?? {};
+ }
+
+ if (map['components'] != null) {
+ return map['components']['schemas'] as Map? ?? {};
+ }
+
+ return {};
+ }
+
+ Map getResponses(dynamic map) {
+ if (map['components'] != null) {
+ return map['components']['responses'] as Map? ?? {};
+ }
+
+ return {};
+ }
+}
diff --git a/api_automatic/lib/src/code_generators/swagger_enums_generator.dart b/api_automatic/lib/src/code_generators/swagger_enums_generator.dart
new file mode 100644
index 0000000..4f28f1d
--- /dev/null
+++ b/api_automatic/lib/src/code_generators/swagger_enums_generator.dart
@@ -0,0 +1,381 @@
+import 'dart:convert';
+import 'package:recase/recase.dart';
+import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
+import 'package:swagger_dart_code_generator/src/exception_words.dart';
+import 'package:swagger_dart_code_generator/src/extensions/string_extension.dart';
+import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request.dart';
+import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request_parameter.dart';
+import 'package:swagger_dart_code_generator/src/swagger_models/swagger_path.dart';
+import 'package:swagger_dart_code_generator/src/swagger_models/swagger_root.dart';
+import 'package:collection/collection.dart';
+
+abstract class SwaggerEnumsGenerator {
+ static const String defaultEnumFieldName = 'value_';
+ static const String defaultEnumValueName = 'swaggerGeneratedUnknown';
+
+ String generate(String swagger, String fileName);
+
+ String generateFromMap(String dartCode, String fileName, Map definitions,
+ Map responses, Map requestBodies) {
+ final enumsFromRequests = generateEnumsContentFromRequests(dartCode, fileName);
+
+ final enumsFromResponses = generateEnumsFromResponses(responses);
+
+ final enumsFromRequestBodies = generateEnumsFromRequestBodies(requestBodies);
+
+ if (definitions.isEmpty) {
+ return '$enumsFromRequests$enumsFromResponses$enumsFromRequestBodies';
+ }
+
+ final enumsFromClasses = definitions.keys
+ .map((String className) {
+ return generateEnumsFromClasses(SwaggerModelsGenerator.getValidatedClassName(className.pascalCase),
+ definitions[className] as Map);
+ })
+ .where((element) => element.isNotEmpty)
+ .join('\n');
+
+ if (enumsFromClasses.isEmpty &&
+ enumsFromRequests.isEmpty &&
+ enumsFromResponses.isEmpty &&
+ enumsFromRequestBodies.isEmpty) {
+ return '';
+ }
+
+ return '''
+import 'package:json_annotation/json_annotation.dart';
+$enumsFromClasses
+
+$enumsFromRequests
+
+$enumsFromResponses
+
+$enumsFromRequestBodies
+''';
+ }
+
+ String generateEnumsFromResponses(Map responses) {
+ if (responses.isEmpty) {
+ return '';
+ }
+
+ final enumsFromResponses = responses.keys
+ .map((String className) {
+ final response = responses[className];
+ final content = response['content'] as Map?;
+ final firstContent = content != null && content.entries.isNotEmpty ? content.entries.first.value : null;
+ final schema = firstContent == null ? null : firstContent['schema'];
+
+ if (schema == null) {
+ return '';
+ }
+
+ return generateEnumsFromClasses(
+ SwaggerModelsGenerator.getValidatedClassName(className.pascalCase), schema as Map);
+ })
+ .where((element) => element.isNotEmpty)
+ .join('\n');
+
+ return enumsFromResponses;
+ }
+
+ String generateEnumsFromRequestBodies(Map requestBodies) {
+ if (requestBodies.isEmpty) {
+ return '';
+ }
+
+ final enumsFromRequestBodies = requestBodies.keys
+ .map((String className) {
+ final response = requestBodies[className];
+ final content = response['content'] as Map?;
+ final firstContent = content != null && content.entries.isNotEmpty ? content.entries.first.value : null;
+ final schema = firstContent == null ? null : firstContent['schema'];
+
+ if (schema == null) {
+ return '';
+ }
+
+ return generateEnumsFromClasses(
+ SwaggerModelsGenerator.getValidatedClassName(className.pascalCase), schema as Map);
+ })
+ .where((element) => element.isNotEmpty)
+ .join('\n');
+
+ return enumsFromRequestBodies;
+ }
+
+ static SwaggerRequestParameter getOriginalOrOverriddenRequestParameter(
+ SwaggerRequestParameter swaggerRequestParameter, List definedParameters) {
+ if (swaggerRequestParameter.ref.isEmpty || definedParameters.isEmpty) {
+ return swaggerRequestParameter;
+ }
+
+ final parameterClassName = swaggerRequestParameter.ref.split('/').last;
+
+ final neededParameter = definedParameters.firstWhere(
+ (SwaggerRequestParameter element) => element.name == parameterClassName || element.key == parameterClassName,
+ orElse: () => swaggerRequestParameter);
+
+ return neededParameter;
+ }
+
+ String generateEnumsContentFromRequests(String swagger, String fileName) {
+ final enumNames = [];
+ final result = StringBuffer();
+ final map = jsonDecode(swagger) as Map;
+ final swaggerRoot = SwaggerRoot.fromJson(map);
+
+ //Link defined parameters with requests
+ swaggerRoot.paths.forEach((String path, SwaggerPath swaggerPath) {
+ swaggerPath.requests.forEach((String requestType, SwaggerRequest swaggerRequest) {
+ swaggerRequest.parameters = swaggerRequest.parameters
+ .map((SwaggerRequestParameter parameter) => getOriginalOrOverriddenRequestParameter(
+ parameter, swaggerRoot.components?.parameters.values.toList() ?? []))
+ .toList();
+ });
+ });
+
+ swaggerRoot.paths.forEach((String path, SwaggerPath swaggerPath) {
+ swaggerPath.requests.forEach((String requestType, SwaggerRequest swaggerRequest) {
+ if (swaggerRequest.parameters.isEmpty) {
+ return;
+ }
+
+ for (var p = 0; p < swaggerRequest.parameters.length; p++) {
+ final swaggerRequestParameter = swaggerRequest.parameters[p];
+
+ var name = SwaggerModelsGenerator.generateRequestEnumName(path, requestType, swaggerRequestParameter.name);
+
+ name = SwaggerModelsGenerator.getValidatedClassName(name);
+
+ if (enumNames.contains(name)) {
+ continue;
+ }
+
+ final enumValues =
+ swaggerRequestParameter.schema?.enumValues ?? swaggerRequestParameter.items?.enumValues ?? [];
+
+ if (enumValues.isNotEmpty) {
+ final enumContent = generateEnumContent(name, enumValues);
+
+ result.writeln(enumContent);
+ enumNames.add(swaggerRequestParameter.name);
+ }
+ }
+ });
+ });
+
+ return result.toString();
+ }
+
+ String generateEnumContent(String enumName, List enumValues) {
+ final enumValuesContent = getEnumValuesContent(enumValues);
+
+ final enumMap =
+ '''
+\n\tconst \$${enumName}Map = {
+\t${getEnumValuesMapContent(enumName, enumValues)}
+ };
+ ''';
+
+ final result =
+ """
+enum $enumName{
+\t@JsonValue('swaggerGeneratedUnknown')
+\tswaggerGeneratedUnknown,
+$enumValuesContent
+}
+
+$enumMap
+ """;
+
+ return result;
+ }
+
+ String getEnumValuesContent(List enumValues) {
+ final result = enumValues
+ .map((String enumFieldName) =>
+ "\t@JsonValue('${enumFieldName.replaceAll("\$", "\\\$")}')\n\t${getValidatedEnumFieldName(enumFieldName)}")
+ .join(',\n');
+
+ return result;
+ }
+
+ String getEnumValuesMapContent(String enumName, List enumValues) {
+ final neededValues = [];
+ neededValues.addAll(enumValues);
+
+ final unknownEnumPart = ',\n\t$enumName.swaggerGeneratedUnknown: \'\'';
+
+ final result = neededValues
+ .map((String enumFieldName) =>
+ '\t$enumName.${getValidatedEnumFieldName(enumFieldName)}: \'${enumFieldName.replaceAll('\$', '\\\$')}\'')
+ .join(',\n') +
+ unknownEnumPart;
+
+ return result;
+ }
+
+ static String getValidatedEnumFieldName(String name) {
+ if (name.isEmpty) {
+ name = 'null';
+ }
+
+ var result = name
+ .replaceAll(RegExp(r'[^\w|\_|)]'), '_')
+ .split('_')
+ .where((element) => element.isNotEmpty)
+ .map((String word) => word.toLowerCase().capitalize)
+ .join();
+
+ if (result.startsWith(RegExp('[0-9]+'))) {
+ result = defaultEnumFieldName + result;
+ }
+
+ if (exceptionWords.contains(result.toLowerCase())) {
+ return '\$' + result.lower;
+ }
+
+ return result.lower;
+ }
+
+ static List getEnumNamesFromRequests(String swagger) {
+ final enumNames = [];
+ final map = jsonDecode(swagger) as Map;
+ final swaggerRoot = SwaggerRoot.fromJson(map);
+
+ //Link defined parameters with requests
+ swaggerRoot.paths.forEach((String path, SwaggerPath swaggerPath) {
+ swaggerPath.requests.forEach((String req, SwaggerRequest swaggerRequest) {
+ swaggerRequest.parameters = swaggerRequest.parameters
+ .map((SwaggerRequestParameter parameter) => getOriginalOrOverriddenRequestParameter(
+ parameter, swaggerRoot.components?.parameters.values.toList() ?? []))
+ .toList();
+ });
+ });
+
+ swaggerRoot.paths.forEach((String path, SwaggerPath swaggerPath) {
+ swaggerPath.requests.forEach((String requestType, SwaggerRequest swaggerRequest) {
+ if (swaggerRequest.parameters.isEmpty) {
+ return;
+ }
+
+ for (var p = 0; p < swaggerRequest.parameters.length; p++) {
+ final swaggerRequestParameter = swaggerRequest.parameters[p];
+
+ var name = SwaggerModelsGenerator.generateRequestEnumName(path, requestType, swaggerRequestParameter.name);
+
+ if (enumNames.contains(name)) {
+ continue;
+ }
+
+ final enumValues =
+ swaggerRequestParameter.schema?.enumValues ?? swaggerRequestParameter.items?.enumValues ?? [];
+
+ if (enumValues.isNotEmpty) {
+ enumNames.add(name);
+ }
+ }
+ });
+ });
+
+ return enumNames;
+ }
+
+ String generateEnumsContentFromModelProperties(Map map, String className) {
+ if (map.isEmpty) {
+ return '';
+ }
+
+ final gemeratedEnumsContent = map.keys
+ .map((String key) {
+ final enumValuesMap = map[key] as Map;
+
+ if (enumValuesMap.containsKey('type')) {
+ return generateEnumContentIfPossible(enumValuesMap, generateEnumName(className, key));
+ }
+
+ return '';
+ })
+ .where((String generatedEnum) => generatedEnum.isNotEmpty)
+ .join('\n');
+
+ return gemeratedEnumsContent;
+ }
+
+ String generateEnumContentIfPossible(Map map, String enumName) {
+ enumName = SwaggerModelsGenerator.getValidatedClassName(enumName);
+
+ if (map['enum'] != null) {
+ final enumValues = map['enum'] as List;
+ final stringValues = enumValues.map((e) => e.toString()).toList();
+ final enumMap =
+ '''
+\n\tconst \$${enumName}Map = {
+\t${getEnumValuesMapContent(enumName, stringValues)}
+ };
+ ''';
+
+ return """
+enum ${enumName.capitalize} {
+\t@JsonValue('$defaultEnumValueName')\n $defaultEnumValueName,
+${generateEnumValuesContent(enumValues)}
+}
+
+$enumMap
+""";
+ } else if (map['items'] != null) {
+ return generateEnumContentIfPossible(map['items'] as Map, enumName);
+ } else {
+ return '';
+ }
+ }
+
+ String generateEnumName(String className, String enumName) {
+ final validatedEnumName = SwaggerModelsGenerator.getValidatedClassName(enumName);
+ return '${className.capitalize}$validatedEnumName';
+ }
+
+ String generateEnumValuesContent(List values) {
+ return values
+ .map((dynamic e) =>
+ "\t@JsonValue('${e.toString().replaceAll("\$", "\\\$")}')\n ${getValidatedEnumFieldName(e.toString())}")
+ .join(',\n');
+ }
+
+ String generateEnumsFromClasses(
+ String className,
+ Map map,
+ ) {
+ if (map['enum'] != null) {
+ return generateEnumContentIfPossible(map, className);
+ }
+
+ if (map['items'] != null && map['items']['enum'] != null) {
+ return generateEnumContentIfPossible(map['items'] as Map, className);
+ }
+ Map properties;
+
+ if (map.containsKey('allOf')) {
+ final allOf = map['allOf'] as List;
+ var propertiesContainer = allOf.firstWhereOrNull(
+ (e) => (e as Map).containsKey('properties'),
+ ) as Map? ??
+ {};
+
+ if (propertiesContainer.isNotEmpty) {
+ properties = propertiesContainer['properties'] as Map? ?? {};
+ } else {
+ properties = map['properties'] as Map? ?? {};
+ }
+ } else {
+ properties = map['properties'] as Map? ?? {};
+ }
+
+ if (properties.isEmpty) {
+ return '';
+ }
+
+ return generateEnumsContentFromModelProperties(properties, className);
+ }
+}
diff --git a/api_automatic/lib/src/code_generators/swagger_models_generator.dart b/api_automatic/lib/src/code_generators/swagger_models_generator.dart
new file mode 100644
index 0000000..cdc942b
--- /dev/null
+++ b/api_automatic/lib/src/code_generators/swagger_models_generator.dart
@@ -0,0 +1,1114 @@
+import 'dart:convert';
+
+import 'package:collection/src/iterable_extensions.dart';
+import 'package:swagger_dart_code_generator/src/code_generators/constants.dart';
+import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
+import 'package:recase/recase.dart';
+import 'package:swagger_dart_code_generator/src/code_generators/v2/swagger_enums_generator_v2.dart';
+import 'package:swagger_dart_code_generator/src/extensions/string_extension.dart';
+import 'package:swagger_dart_code_generator/src/exception_words.dart';
+import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
+
+import 'constants.dart';
+
+abstract class SwaggerModelsGenerator {
+ static const List keyClasses = ['Response', 'Request'];
+
+ String generate(String dartCode, String fileName, GeneratorOptions options, Map requestClass);
+ String generateResponses(String dartCode, String fileName, GeneratorOptions options);
+
+ String generateRequestBodies(String dartCode, String fileName, GeneratorOptions options);
+ String getExtendsString(Map map);
+ List getAllEnumNames(String swaggerFile);
+ List getAllListEnumNames(String swaggerFile);
+
+ String generateModelClassContent(
+ String className,
+ Map map,
+ Map schemas,
+ List defaultValues,
+ bool useDefaultNullForLists,
+ List allEnumNames,
+ List allEnumListNames,
+ GeneratorOptions options) {
+ if (map['enum'] != null) {
+ return '';
+ }
+
+ if (kBasicTypes.contains(map['type'].toString().toLowerCase())) {
+ return '';
+ }
+
+ if (map['type'] == 'array' && map['items'] != null && map['items']['type'] == 'enum') {
+ return '';
+ }
+
+ if (map.containsKey('\$ref')) {
+ return 'class $className {}';
+ }
+
+ return generateModelClassString(
+ className,
+ map,
+ schemas,
+ defaultValues,
+ useDefaultNullForLists,
+ allEnumNames,
+ allEnumListNames,
+ options,
+ );
+ }
+
+ static Map getClassesFromInnerClasses(
+ Map classes,
+ GeneratorOptions options,
+ ) {
+ final result = {};
+
+ classes.forEach((classKey, classValue) {
+ final properties = classValue['properties'] as Map?;
+
+ if (properties == null) {
+ return;
+ }
+
+ properties.forEach((propertyKey, propertyValue) {
+ final innerClassName = '${getValidatedClassName(classKey)}\$${getValidatedClassName(propertyKey)}';
+
+ if (propertyValue['properties'] != null) {
+ result[innerClassName] = propertyValue;
+ }
+
+ final items = propertyValue['items'] as Map?;
+
+ if (items != null && items['properties'] != null) {
+ result[innerClassName] = propertyValue;
+ }
+ });
+ });
+
+ if (result.isNotEmpty) {
+ result.addAll(getClassesFromInnerClasses(result, options));
+ }
+
+ return result;
+ }
+
+ static Map getClassesFromResponses(String dartCode, GeneratorOptions options) {
+ final swagger = jsonDecode(dartCode);
+
+ final results = {};
+
+ final paths = swagger['paths'] as Map?;
+ if (paths == null) {
+ return results;
+ }
+
+ paths.forEach((path, pathValue) {
+ final requests = pathValue as Map;
+
+ requests.removeWhere((key, value) => key == 'parameters' || key == 'summary');
+
+ requests.forEach((request, requestValue) {
+ if (!supportedRequestTypes.contains(request.toLowerCase())) {
+ return;
+ }
+
+ if (options.excludePaths.isNotEmpty &&
+ options.excludePaths.any((exclPath) => RegExp(exclPath).hasMatch(request))) {
+ return;
+ }
+
+ if (options.includePaths.isNotEmpty &&
+ !options.includePaths.any((inclPath) => RegExp(inclPath).hasMatch(request))) {
+ return;
+ }
+ final responses = requestValue['responses'] as Map;
+
+ final neededResponse = responses['200'];
+
+ if (neededResponse != null &&
+ neededResponse['schema'] != null &&
+ neededResponse['schema']['type'] == 'object' &&
+ neededResponse['schema']['properties'] != null) {
+ final pathText = path.split('/').map((e) => e.pascalCase).join();
+ final requestText = request.pascalCase;
+
+ results['$pathText$requestText\$Response'] = neededResponse['schema'];
+ }
+ });
+ });
+
+ return results;
+ }
+
+ String generateBase(String dartCode, String fileName, GeneratorOptions options, Map classes,
+ bool generateFromJsonToJsonForRequests, Map requestClass) {
+ final allEnumsNames = getAllEnumNames(dartCode);
+ final allEnumListNames = getAllListEnumNames(dartCode);
+
+ final generatedEnumFromJsonToJson = generateFromJsonToJsonForRequests
+ ? genetateEnumFromJsonToJsonMethods(allEnumsNames, options.enumsCaseSensitive)
+ : '';
+
+ final classesFromResponses = getClassesFromResponses(dartCode, options);
+ classes.addAll(classesFromResponses);
+
+ final classesFromInnerClasses = getClassesFromInnerClasses(classes, options);
+
+ classes.addAll(classesFromInnerClasses);
+
+ // requestClass[requestClass.keys.first] = {
+ // 'type': 'object',
+ // };
+
+ classes.addAll(requestClass);
+
+ if (classes.isEmpty) {
+ return '';
+ }
+
+ final generatedClasses = classes.keys.map((String className) {
+ if (classes['enum'] != null) {
+ return '';
+ }
+
+ return generateModelClassContent(
+ className.pascalCase,
+ classes[className] as Map,
+ classes,
+ options.defaultValuesMap,
+ options.useDefaultNullForLists,
+ allEnumsNames,
+ allEnumListNames,
+ options,
+ );
+ }).join('\n');
+
+ var results = '$generatedClasses\n$generatedEnumFromJsonToJson';
+
+ final listEnums = getAllListEnumNames(dartCode);
+
+ listEnums.forEach((listEnum) {
+ results = results.replaceAll(' $listEnum ', ' List<$listEnum> ');
+ });
+
+ return results;
+ }
+
+ static String getValidatedClassName(String className) {
+ if (kBasicTypes.contains(className)) {
+ return className;
+ }
+
+ if (exceptionWords.contains(className)) {
+ return 'Object';
+ }
+
+ if (className.isEmpty) {
+ return className;
+ }
+
+ final isEnum = className.startsWith('enums.');
+
+ if (isEnum) {
+ className = className.substring(6);
+ }
+
+ final words = className.split('\$');
+
+ final result =
+ words.map((e) => e.pascalCase.split(RegExp(r'\W+|\_')).map((String str) => str.capitalize).join()).join('\$');
+
+ if (keyClasses.contains(result)) {
+ return '$result\$';
+ }
+
+ if (isEnum) {
+ return 'enums.$result';
+ }
+
+ if (result.startsWith(RegExp('[0-9]'))) {
+ return '\$$result';
+ }
+
+ return result;
+ }
+
+ static String getValidatedParameterName(String parameterName) {
+ if (parameterName.isEmpty) {
+ return parameterName;
+ }
+
+ final isEnum = parameterName.startsWith('enums.');
+
+ if (isEnum) {
+ parameterName = parameterName.substring(6);
+ }
+
+ final words = parameterName.split('\$');
+
+ final result =
+ words.map((e) => e.pascalCase.split(RegExp(r'\W+|\_')).map((String str) => str.capitalize).join()).join('\$');
+
+ if (isEnum) {
+ return 'enums.$result';
+ }
+
+ if (exceptionWords.contains(result.camelCase) || kBasicTypes.contains(result.camelCase)) {
+ return '\$$parameterName';
+ }
+
+ if (result.isEmpty) {
+ return kUndefinedParameter;
+ }
+
+ return result.camelCase;
+ }
+
+ String getParameterTypeName(
+ String className,
+ String parameterName,
+ Map parameter,
+ String modelPostfix,
+ String? refNameParameter,
+ ) {
+ if (parameter['properties'] != null) {
+ return '${getValidatedClassName(className)}\$${getValidatedClassName(parameterName)}$modelPostfix';
+ }
+
+ if (refNameParameter != null) {
+ return refNameParameter.pascalCase;
+ }
+
+ if (parameter.isEmpty) {
+ return 'Object';
+ }
+
+ if (parameter['\$ref'] != null) {
+ return parameter['\$ref'].toString().split('/').last.pascalCase;
+ }
+
+ switch (parameter['type'] as String?) {
+ case 'integer':
+ case 'int':
+ case 'int32':
+ case 'int64':
+ return 'int';
+ case 'boolean':
+ return 'bool';
+ case 'string':
+ if (parameter['format'] == 'date-time' || parameter['format'] == 'date') {
+ return 'DateTime';
+ } else if (parameter['enum'] != null) {
+ //todo
+ return 'int'; //'enums.${SwaggerModelsGenerator.getValidatedClassName(SwaggerEnumsGeneratorV2().generateEnumName(SwaggerModelsGenerator.getValidatedClassName(className), parameterName))}';
+ }
+ return 'String';
+ case 'Date':
+ return 'DateTime';
+ case 'number':
+ return 'double';
+ case 'object':
+ return 'Object';
+ case 'array':
+ final items = parameter['items'] as Map? ?? {};
+ final typeName = getParameterTypeName(className, parameterName, items, modelPostfix, null);
+ return 'List<$typeName>';
+ default:
+ return 'Object';
+ }
+ }
+
+ static String generateFieldName(String jsonKey) {
+ final forbiddenCharacters = ['#'];
+
+ jsonKey = jsonKey.camelCase;
+
+ forbiddenCharacters.forEach((String element) {
+ if (jsonKey.startsWith(element)) {
+ jsonKey = '\$forbiddenFieldName';
+ }
+ });
+
+ if (jsonKey.startsWith(RegExp('[0-9]')) || exceptionWords.contains(jsonKey)) {
+ jsonKey = '\$' + jsonKey;
+ }
+
+ if (kBasicTypes.contains(jsonKey)) {
+ jsonKey = '\$' + jsonKey;
+ }
+
+ return jsonKey;
+ }
+
+ static String generateRequestEnumName(String path, String requestType, String parameterName) {
+ if (path == '/') {
+ path = '\$';
+ }
+
+ path = path.split('{').map((e) => e.capitalize).join();
+ path = path.split('}').map((e) => e.capitalize).join();
+
+ final correctedPath = generateFieldName(path);
+
+ final result = '${correctedPath.capitalize}${requestType.capitalize}${parameterName.capitalize}';
+
+ return SwaggerModelsGenerator.getValidatedClassName(result);
+ }
+
+ /// Tạo tên hàm từ path + requestType, gồm cả segment path để tránh trùng (vd: /v1/product/delete/{id} -> productDeleteId).
+ static String generateRequestName(String path, String requestType) {
+ if (path == '/') {
+ path = '\$';
+ }
+
+ final segments = path
+ .split('/')
+ .where((e) => e.isNotEmpty)
+ .map((e) {
+ if (e.startsWith('{') && e.endsWith('}')) {
+ return e.substring(1, e.length - 1);
+ }
+ return e;
+ })
+ .where((e) => e.isNotEmpty && !RegExp(r'^v\d+').hasMatch(e.toLowerCase()))
+ .toList();
+
+ // Bỏ segment 'api' ở đầu nếu có để tên hàm không bắt đầu bằng 'api'
+ if (segments.isNotEmpty && segments.first.toLowerCase() == 'api') {
+ segments.removeAt(0);
+ }
+
+ if (segments.isEmpty) {
+ return requestType.camelCase;
+ }
+
+ final pathPart = segments.map((s) => s.capitalize).join();
+ final correctedPath = SwaggerModelsGenerator.getValidatedClassName(pathPart);
+ return correctedPath.camelCase;
+ }
+
+ String generateDefaultValueFromMap(DefaultValueMap map) {
+ switch (map.typeName) {
+ case 'int':
+ case 'double':
+ case 'bool':
+ return map.defaultValue;
+ default:
+ return "'${map.defaultValue}'";
+ }
+ }
+
+ String generateIncludeIfNullString(GeneratorOptions options) {
+ if (options.includeIfNull == null) {
+ return '';
+ }
+
+ return ', includeIfNull: ${options.includeIfNull}';
+ }
+
+ String generatePropertyContentByDefault(Map propertyEntryMap, String propertyName,
+ List allEnumNames, List allEnumListNames, GeneratorOptions options) {
+ var typeName = '';
+ final originalRef = propertyEntryMap['originalRef'];
+
+ if (originalRef != null) {
+ typeName = getValidatedClassName(propertyEntryMap['originalRef'].toString());
+ }
+
+ if (typeName.isEmpty) {
+ typeName = kDynamic;
+ }
+
+ final unknownEnumValue = generateUnknownEnumValue(allEnumNames, allEnumListNames, typeName.toString(), false);
+
+ final dateToJsonValue = generateToJsonForDate(propertyEntryMap);
+
+ final includeIfNullString = generateIncludeIfNullString(options);
+
+ if (typeName != kDynamic) {
+ //typeName += '?';
+ }
+//Todo final
+ final jsonKeyContent = "@JsonKey(name: '$propertyName'$includeIfNullString$dateToJsonValue$unknownEnumValue)\n";
+ return '\t$jsonKeyContent\t $typeName ${SwaggerModelsGenerator.generateFieldName(propertyName)};';
+ }
+ //final
+
+ String generateUnknownEnumValue(
+ List allEnumNames, List allEnumListNames, String typeName, bool isList) {
+ typeName = getValidatedClassName(typeName);
+
+ if (allEnumListNames.contains(typeName)) {
+ isList = true;
+ }
+
+ if (allEnumNames.contains(typeName)) {
+ if (!isList) {
+ final enumNameCamelCase = typeName.replaceAll('enums.', '').camelCase;
+ return ', toJson: ${enumNameCamelCase}ToJson, fromJson: ${enumNameCamelCase}FromJson';
+ } else {
+ final enumNameCamelCase = typeName.replaceAll('enums.', '').camelCase;
+ return ', toJson: ${enumNameCamelCase}ListToJson, fromJson: ${enumNameCamelCase}ListFromJson';
+ }
+ }
+
+ return '';
+ }
+
+ String generateToJsonForDate(Map map) {
+ // Không dùng helper _dateToJson để tránh lỗi thiếu hàm trong file sinh ra.
+ // Mặc định để json_serializable serialize DateTime theo ISO8601.
+ return '';
+ }
+
+ String generatePropertyContentBySchema(
+ Map propertyEntryMap,
+ String propertyName,
+ String propertyKey,
+ String className,
+ List allEnumNames,
+ List allEnumListNames,
+ GeneratorOptions options,
+ Map basicTypesMap) {
+ final propertySchema = propertyEntryMap['schema'] as Map;
+ var parameterName = propertySchema['\$ref'].toString().split('/').last;
+
+ String typeName;
+ if (basicTypesMap.containsKey(parameterName)) {
+ typeName = basicTypesMap[parameterName]!;
+ } else {
+ typeName = getValidatedClassName(
+ getParameterTypeName(className, propertyName, propertyEntryMap, options.modelPostfix, parameterName));
+ }
+
+ final includeIfNullString = generateIncludeIfNullString(options);
+
+ final allEnumsNamesWithoutPrefix = allEnumNames.map((e) => e.replaceFirst('enums.', '')).toList();
+
+ if (allEnumsNamesWithoutPrefix.contains(typeName)) {
+ typeName = 'enums.$typeName';
+ } else {
+ typeName += options.modelPostfix;
+ }
+
+ final unknownEnumValue = generateUnknownEnumValue(allEnumNames, allEnumListNames, typeName, false);
+
+ final dateToJsonValue = generateToJsonForDate(propertyEntryMap);
+
+ final jsonKeyContent = "@JsonKey(name: '$propertyKey'$includeIfNullString$unknownEnumValue$dateToJsonValue)\n";
+
+ //toDo \tfinal
+ return '\t$jsonKeyContent\t $typeName? ${SwaggerModelsGenerator.generateFieldName(propertyName)};';
+ }
+
+ String generatePropertyContentByRef(
+ Map propertyEntryMap,
+ String propertyName,
+ String propertyKey,
+ String className,
+ List allEnumNames,
+ List allEnumListNames,
+ GeneratorOptions options,
+ Map basicTypesMap) {
+ final parameterName = propertyEntryMap['\$ref'].toString().split('/').last;
+ String typeName;
+ if (basicTypesMap.containsKey(parameterName)) {
+ typeName = basicTypesMap[parameterName]!;
+ } else {
+ typeName = getValidatedClassName(
+ getParameterTypeName(className, propertyName, propertyEntryMap, options.modelPostfix, parameterName));
+ }
+
+ final allEnumsNamesWithoutPrefix = allEnumNames.map((e) => e.replaceFirst('enums.', '')).toList();
+
+ typeName = SwaggerModelsGenerator.getValidatedClassName(typeName);
+
+ if (allEnumsNamesWithoutPrefix.contains(typeName)) {
+ typeName = 'enums.$typeName';
+ } else if (!basicTypesMap.containsKey(parameterName) && !allEnumListNames.contains(typeName)) {
+ typeName += options.modelPostfix;
+ }
+
+ final unknownEnumValue = generateUnknownEnumValue(allEnumNames, allEnumListNames, typeName, false);
+
+ if (allEnumListNames.contains(typeName)) {
+ typeName = 'List<$typeName>';
+ }
+
+ final includeIfNullString = generateIncludeIfNullString(options);
+
+ final jsonKeyContent = "@JsonKey(name: '$propertyKey'$includeIfNullString$unknownEnumValue)\n";
+//toDo \tfinal
+ return '\t$jsonKeyContent\t $typeName? $propertyName;';
+ }
+
+ String generateEnumPropertyContent(
+ String key,
+ String className,
+ List allEnumNames,
+ List allEnumListNames,
+ GeneratorOptions options,
+ ) {
+ final enumName =
+ SwaggerModelsGenerator.getValidatedClassName(SwaggerEnumsGeneratorV2().generateEnumName(className, key));
+
+ allEnumNames.add(enumName);
+
+ final unknownEnumValue = generateUnknownEnumValue(allEnumNames, allEnumListNames, enumName, false).substring(2);
+
+ final includeIfNullString = generateIncludeIfNullString(options);
+
+ return '''
+ @JsonKey($unknownEnumValue$includeIfNullString)
+ final ${className.capitalize + key.capitalize}? ${SwaggerModelsGenerator.generateFieldName(key)};''';
+ }
+
+ String generateListPropertyContent(
+ String propertyName,
+ String propertyKey,
+ String className,
+ Map propertyEntryMap,
+ bool useDefaultNullForLists,
+ List allEnumNames,
+ List allEnumListNames,
+ GeneratorOptions options,
+ Map basicTypesMap) {
+ final items = propertyEntryMap['items'];
+
+ var typeName = '';
+ if (items != null) {
+ typeName = getValidatedClassName(items['originalRef'] as String? ?? '');
+
+ if (typeName.isNotEmpty && !kBasicTypes.contains(typeName.toLowerCase())) {
+ typeName += options.modelPostfix;
+ }
+
+ if (typeName.isEmpty) {
+ final ref = items['\$ref'] as String?;
+ if (ref?.isNotEmpty == true) {
+ typeName = ref!.split('/').last;
+
+ if (!allEnumListNames.contains(typeName) &&
+ !allEnumNames.contains('enums.' + typeName) &&
+ !basicTypesMap.containsKey(typeName)) {
+ typeName += options.modelPostfix;
+ }
+ }
+
+ if (basicTypesMap.containsKey(typeName)) {
+ typeName = basicTypesMap[typeName]!;
+ } else if (typeName != kDynamic) {
+ typeName = typeName.pascalCase;
+ }
+ } else if (!allEnumNames.contains('enums.$typeName') && !kBasicTypes.contains(typeName.toLowerCase())) {
+ typeName = kBasicTypesMap[typeName] ?? typeName + options.modelPostfix;
+ }
+
+ if (typeName.isNotEmpty) {
+ typeName = SwaggerModelsGenerator.getValidatedClassName(typeName);
+ }
+
+ if (typeName.isEmpty) {
+ if (items['type'] == 'array' || items['items'] != null) {
+ typeName = 'List