API tự động Swagger

This commit is contained in:
minhhieu2312 2026-02-26 14:28:55 +07:00
parent 8fea656229
commit 81410f6f15
79 changed files with 47302 additions and 6 deletions

488
api_automatic/CHANGELOG.md Normal file
View File

@ -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

201
api_automatic/LICENSE Normal file
View File

@ -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.

153
api_automatic/README.md Normal file
View File

@ -0,0 +1,153 @@
<p align="center">
<img src="https://raw.githubusercontent.com/epam-cross-platform-lab/swagger-dart-code-generator/master/assets/lib_full_logo.png" height="100" alt="Swagger dart code generator" />
</p>
Code partially generated with [chopper](https://pub.dev/packages/chopper)
# :mega: **Build dart types from Swagger/OpenAPI schemas**
[![pub package](https://img.shields.io/pub/v/swagger_dart_code_generator.svg)](https://pub.dartlang.org/packages/swagger_dart_code_generator)
![GitHub issues](https://img.shields.io/github/issues-raw/epam-cross-platform-lab/swagger-dart-code-generator?style=flat-square)
![GitHub last commit](https://img.shields.io/github/last-commit/epam-cross-platform-lab/swagger-dart-code-generator?style=flat-square)
<a href="https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/actions"><img src="https://img.shields.io/github/workflow/status/epam-cross-platform-lab/swagger-dart-code-generator/CI%20for%20master%20branch/master" alt="build"></a>
<a href="https://discord.gg/fmkN37"><img src="https://img.shields.io/discord/755005482405462017.svg?logo=discord&color=blue" alt="Discord"></a>
[![codecov](https://codecov.io/gh/epam-cross-platform-lab/swagger-dart-code-generator/branch/master/graph/badge.svg)](https://codecov.io/gh/epam-cross-platform-lab/swagger-dart-code-generator)
<a href="https://github.com/epam-cross-platform-lab/swagger-dart-code-generator"><img src="https://img.shields.io/github/stars/epam-cross-platform-lab/swagger-dart-code-generator?style=social" alt="Discord"></a>
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. </br>
<b>.dart</b> generated by <b>Swagger dart code generator</b>, contains all models, requests, converters, etc.</br>
[Since v1.2.0] <b>.enums.dart</b> generated by <b>Swagger dart code generator</b>, contains all enums and enums mappings.</br>
<b>.chopper.dart</b> - generated by <a href="https://pub.dev/packages/chopper">chopper</a>.</br>
<b>.g.dart</b> - generated by <a href="https://pub.dev/packages/json_serializable">json_serializable</a>.</br>
<img src="https://raw.githubusercontent.com/epam-cross-platform-lab/swagger-dart-code-generator/master/assets/overview_image.png" width="320" alt="Bloc" />
## **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<String> of Regex If not empty - includes only paths matching reges |
| `exclude_paths` | `[]` | `false` | List<String> 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<String>'
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<dynamic>'
- 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.

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

14
api_automatic/build.yaml Normal file
View File

@ -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"]

View File

@ -0,0 +1,67 @@
const List<String> successResponseCodes = [
'200',
'201',
];
const List<String> 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<dynamic>';
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 = <String, String>{
'integer': 'int',
'int': 'int',
'int32': 'int',
'int64': 'int',
'boolean': 'bool',
'bool': 'bool',
'string': 'String',
'file': 'List<String>',
'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
// **************************************************************************
''';

View File

@ -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<String, List<String>> 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<String, List<String>> buildExtensions, bool hasModels, GeneratorOptions options) {
if (!hasModels) {
return '';
}
final maps = StringBuffer();
final imports = <String>[];
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<Type, Object Function(Map<String, dynamic>)> $mappingVariableName = {
$maps};
''';
return mapping;
}
///Generated imports for concrete service
String generateImportsContent(
String swaggerFileName,
bool hasModels,
bool buildOnlyModels,
bool hasEnums,
bool separateModels,
List<String> 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> = T Function(Map<String, dynamic> json);
class \$CustomJsonDecoder {
\$CustomJsonDecoder(this.factories);
final Map<Type, \$JsonFactory> factories;
dynamic decode<T>(dynamic entity) {
if (entity is Iterable) {
return _decodeList<T>(entity);
}
if (entity is T) {
return entity;
}
if (entity is Map<String, dynamic>) {
return _decodeMap<T>(entity);
}
return entity;
}
T _decodeMap<T>(Map<String, dynamic> values) {
final jsonFactory = factories[T];
if (jsonFactory == null || jsonFactory is! \$JsonFactory<T>) {
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<T> _decodeList<T>(Iterable values) =>
values.where((v) => v != null).map<T>((v) => decode<T>(v) as T).toList();
}
class \$JsonSerializableConverter extends chopper.JsonConverter {
@override
chopper.Response<ResultType> convertResponse<ResultType, Item>(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<ResultType>(
body: \$jsonDecoder.decode<Item>(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;
}
}

View File

@ -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<Type, Object Function(Map<String, dynamic>)> ${fileName.pascalCase}$converterClassEnding =
{
${_generateModelsMapping(dartCode, options)}};''';
}
String _generateModelsMapping(String dartCode, GeneratorOptions options) {
final result = <String>[];
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<String, dynamic>?;
final content = response == null ? null : response['content'] as Map<String, dynamic>?;
final firstContent =
content == null || content.entries.isEmpty ? null : content.entries.first.value as Map<String, dynamic>?;
final schema = firstContent == null ? null : firstContent['schema'] as Map<String, dynamic>?;
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<String, dynamic> getDefinitions(dynamic map) {
if (map['definitions'] != null) {
return map['definitions'] as Map<String, dynamic>? ?? {};
}
if (map['components'] != null) {
return map['components']['schemas'] as Map<String, dynamic>? ?? {};
}
return {};
}
Map<String, dynamic> getResponses(dynamic map) {
if (map['components'] != null) {
return map['components']['responses'] as Map<String, dynamic>? ?? {};
}
return {};
}
}

View File

@ -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<String, dynamic> definitions,
Map<String, dynamic> responses, Map<String, dynamic> 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<String, dynamic>);
})
.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<String, dynamic> responses) {
if (responses.isEmpty) {
return '';
}
final enumsFromResponses = responses.keys
.map((String className) {
final response = responses[className];
final content = response['content'] as Map<String, dynamic>?;
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<String, dynamic>);
})
.where((element) => element.isNotEmpty)
.join('\n');
return enumsFromResponses;
}
String generateEnumsFromRequestBodies(Map<String, dynamic> requestBodies) {
if (requestBodies.isEmpty) {
return '';
}
final enumsFromRequestBodies = requestBodies.keys
.map((String className) {
final response = requestBodies[className];
final content = response['content'] as Map<String, dynamic>?;
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<String, dynamic>);
})
.where((element) => element.isNotEmpty)
.join('\n');
return enumsFromRequestBodies;
}
static SwaggerRequestParameter getOriginalOrOverriddenRequestParameter(
SwaggerRequestParameter swaggerRequestParameter, List<SwaggerRequestParameter> 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 = <String>[];
final result = StringBuffer();
final map = jsonDecode(swagger) as Map<String, dynamic>;
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<String> 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<String> enumValues) {
final result = enumValues
.map((String enumFieldName) =>
"\t@JsonValue('${enumFieldName.replaceAll("\$", "\\\$")}')\n\t${getValidatedEnumFieldName(enumFieldName)}")
.join(',\n');
return result;
}
String getEnumValuesMapContent(String enumName, List<String> enumValues) {
final neededValues = <String>[];
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<String> getEnumNamesFromRequests(String swagger) {
final enumNames = <String>[];
final map = jsonDecode(swagger) as Map<String, dynamic>;
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<String, dynamic> map, String className) {
if (map.isEmpty) {
return '';
}
final gemeratedEnumsContent = map.keys
.map((String key) {
final enumValuesMap = map[key] as Map<String, dynamic>;
if (enumValuesMap.containsKey('type')) {
return generateEnumContentIfPossible(enumValuesMap, generateEnumName(className, key));
}
return '';
})
.where((String generatedEnum) => generatedEnum.isNotEmpty)
.join('\n');
return gemeratedEnumsContent;
}
String generateEnumContentIfPossible(Map<String, dynamic> map, String enumName) {
enumName = SwaggerModelsGenerator.getValidatedClassName(enumName);
if (map['enum'] != null) {
final enumValues = map['enum'] as List<dynamic>;
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<String, dynamic>, enumName);
} else {
return '';
}
}
String generateEnumName(String className, String enumName) {
final validatedEnumName = SwaggerModelsGenerator.getValidatedClassName(enumName);
return '${className.capitalize}$validatedEnumName';
}
String generateEnumValuesContent(List<dynamic> values) {
return values
.map((dynamic e) =>
"\t@JsonValue('${e.toString().replaceAll("\$", "\\\$")}')\n ${getValidatedEnumFieldName(e.toString())}")
.join(',\n');
}
String generateEnumsFromClasses(
String className,
Map<String, dynamic> map,
) {
if (map['enum'] != null) {
return generateEnumContentIfPossible(map, className);
}
if (map['items'] != null && map['items']['enum'] != null) {
return generateEnumContentIfPossible(map['items'] as Map<String, dynamic>, className);
}
Map<String, dynamic> properties;
if (map.containsKey('allOf')) {
final allOf = map['allOf'] as List<dynamic>;
var propertiesContainer = allOf.firstWhereOrNull(
(e) => (e as Map<String, dynamic>).containsKey('properties'),
) as Map<String, dynamic>? ??
{};
if (propertiesContainer.isNotEmpty) {
properties = propertiesContainer['properties'] as Map<String, dynamic>? ?? {};
} else {
properties = map['properties'] as Map<String, dynamic>? ?? {};
}
} else {
properties = map['properties'] as Map<String, dynamic>? ?? {};
}
if (properties.isEmpty) {
return '';
}
return generateEnumsContentFromModelProperties(properties, className);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,866 @@
import 'dart:convert';
import 'package:code_builder/code_builder.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.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/responses/swagger_response.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.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:recase/recase.dart';
import 'package:collection/collection.dart';
import 'package:swagger_dart_code_generator/src/extensions/parameter_extensions.dart';
import 'constants.dart';
class SwaggerRequestsGenerator {
String generate({
required String code,
required String className,
required String fileName,
required GeneratorOptions options,
required Map<String, dynamic> requestClass,
}) {
final map = jsonDecode(code) as Map<String, dynamic>;
final swaggerRoot = SwaggerRoot.fromJson(map);
swaggerRoot.paths = _processVersion(swaggerRoot, options);
final service = _generateService(swaggerRoot, className, fileName, options, requestClass);
return service.accept(DartEmitter()).toString();
}
Map<String, SwaggerPath> _processVersion(SwaggerRoot content, GeneratorOptions options) {
var returnValues = <String, SwaggerPath>{};
// ignore: unused_local_variable
content.paths.forEach((key, value) {
if (options.urlParterns.isEmpty ||
options.urlParterns.where((element) => key.toLowerCase().contains(element.toLowerCase())).isNotEmpty) {
if (options.customApiVersion.isNotEmpty) {
options.customApiVersion.forEach((element) {
for (var temp in element.urls) {
if (key.toLowerCase() == temp.toLowerCase()) {
key = key.replaceAll('{version}', element.version);
}
}
});
}
//else {
if (key.contains('{version}')) key = key.replaceAll('{version}', options.defaultApiVersion);
//}
returnValues[key] = value;
}
});
return returnValues;
}
Class _generateService(
SwaggerRoot swaggerRoot,
String className,
String fileName,
GeneratorOptions options,
Map<String, dynamic> requestClass,
) {
final allMethodsContent = _getAllMethodsContent(
swaggerRoot: swaggerRoot,
options: options,
requestClass: requestClass,
);
// final chopperClient = SwaggerAdditionsGenerator.getChopperClientContent(
// className,
// swaggerRoot.host,
// swaggerRoot.basePath,
// options,
// );
var constructor = Constructor((p) => p
..factory = true
..redirect = Reference('_$className')
..requiredParameters.add(
Parameter((p) => p
..type = Reference('Dio')
..name = 'dio'),
)
..optionalParameters.add(
Parameter((p) => p
..type = Reference('String')
..name = 'baseUrl'
..named = true),
));
return Class(
(c) => c
..methods.addAll([...allMethodsContent])
..constructors.add(constructor)
//..extend = Reference(kChopperService)
..docs.add(kServiceHeader)
..annotations.add(refer(kRetrofitApi).call(
[],
)) //{'baseUrl': Reference('ApiPath.EXAM')}
..abstract = true
..name = className,
);
}
List<Method> _getAllMethodsContent({
required SwaggerRoot swaggerRoot,
required GeneratorOptions options,
required Map<String, dynamic> requestClass,
}) {
final methods = <Method>[];
swaggerRoot.paths.forEach((String path, SwaggerPath swaggerPath) {
swaggerPath.requests.forEach((String requestType, SwaggerRequest swaggerRequest) {
if (requestType.toLowerCase() == kRequestTypeOptions) {
return;
}
final item = options.excludePaths
.firstWhereOrNull((excludePath) => excludePath.startsWith(path)); //RegExp(excludePath).hasMatch(path)
print(path);
if (item != null) {
if (item.contains(' ')) {
final temps = item.split(' ');
print("Method: " + temps[temps.length - 1].toLowerCase());
print("Method 2: " + requestType.toLowerCase());
if (temps[temps.length - 1].toLowerCase() == requestType.toLowerCase()) return;
} else {
return;
}
}
if (options.includePaths.isNotEmpty &&
!options.includePaths.any((includePath) => RegExp(includePath).hasMatch(path))) {
return;
}
final methodName = _getRequestMethodName(
requestType: requestType, swaggerRequest: swaggerRequest, path: path, options: options);
// Nếu đã method trùng tên (thường do khác HTTP method trên cùng path)
// thì thêm prefix theo method (get/put/post/delete...) đ tránh trùng,
// dụ: GET /order/{id} -> orderId, PUT /order/{id} -> putOrderId.
var effectiveMethodName = methodName;
if (methods.any((m) => m.name == methodName)) {
effectiveMethodName = '${requestType.toLowerCase()}${methodName.capitalize}';
}
final parameters = _getAllParameters(
swaggerRequest: swaggerRequest,
ignoreHeaders: options.ignoreHeaders,
modelPostfix: options.modelPostfix,
swaggerPath: swaggerPath,
path: path,
requestType: requestType,
root: swaggerRoot,
options: options,
);
// Override request params
final temp = options.requestOverrideValueMap
.firstWhereOrNull((element) => element.url == path && element.method == 'get');
// print(path);
if (temp != null) {
var name = temp.overriddenValue;
parameters.clear();
parameters.add(
Parameter((p) => p
..name = name.camelCase
..named = true
..type = Reference(name.capitalize)
..annotations.add(
refer('Queries').call([]),
)
..named = true),
);
} else if (parameters.length > 2) {
var temps = <String, dynamic>{};
for (var item in _getParameter(swaggerRequest.parameters, options.ignoreHeaders, options.includePaths)) {
if (item.schema != null) {
var instance = item.schema!;
temps[item.name] = {'type': instance.type, 'required': item.isRequired};
}
}
var name = effectiveMethodName + 'Request';
requestClass[name] = {'type': 'object', 'properties': temps};
parameters.clear();
parameters.add(
Parameter((p) => p
..name = name.camelCase
..named = true
..type = Reference(name.capitalize)
..annotations.add(
refer('Queries').call([]),
)
..named = true),
);
}
final returnTypeName = _getReturnTypeName(
responses: swaggerRequest.responses,
path: path,
methodName: effectiveMethodName,
modelPostfix: options.modelPostfix,
swaggerRoot: swaggerRoot,
overridenResponses: options.responseOverrideValueMap.asMap().map((key, value) => MapEntry(value.url, value)),
);
final returns = returnTypeName.isEmpty ? kFutureResponse : returnTypeName.asFutureResponse();
final hasOptionalBody = ['post', 'put', 'patch'].contains(requestType) &&
swaggerRequest.parameters.none((p) => p.inParameter == kBody) &&
swaggerRequest.requestBody == null;
final method = Method((m) => m
..requiredParameters.addAll(parameters)
..docs.add(_getCommentsForMethod(
methodDescription: swaggerRequest.summary,
parameters: swaggerRequest.parameters,
options: options,
))
..name = effectiveMethodName
..annotations.add(_getMethodAnnotation(requestType, path, hasOptionalBody))
..returns = Reference(returns));
if (_hasEnumProperties(method)) {
final privateMethod = _getPrivateMethod(method);
final publicMethod = _getPublicMethod(method);
methods.addAll([publicMethod, privateMethod]);
} else {
methods.add(method);
}
});
});
return methods;
}
bool _hasEnumProperties(Method method) {
return method.optionalParameters.any((p) => p.type!.symbol!.startsWith('enums') == true);
}
Method _getPrivateMethod(Method method) {
final parameters = method.optionalParameters.map((p) {
if (p.type!.symbol!.startsWith('enums.')) {
return p.copyWith(type: Reference('String?'));
}
return p;
});
return Method(
(m) => m
..optionalParameters.addAll(parameters)
..docs.addAll(method.docs)
..name = '_${method.name}'
..annotations.addAll(method.annotations)
..returns = method.returns,
);
}
Method _getPublicMethod(Method method) {
final parameters = method.optionalParameters.map((p) => p.copyWith(annotations: []));
return Method(
(m) => m
..optionalParameters.addAll(parameters)
..docs.addAll(method.docs)
..name = method.name
..returns = method.returns
..body = _generatePublicMethodReturn(parameters, method.name!),
);
}
Code _generatePublicMethodReturn(Iterable<Parameter> parameters, String publicMethodName) {
final parametersListString = parameters.map((p) {
if (p.type!.symbol!.startsWith('enums.')) {
final enumName = p.type!.symbol!.replaceFirst('enums.', '').replaceAll('?', '');
return '${p.name} : enums.\$${enumName}Map[${p.name}]';
}
return '${p.name} : ${p.name}';
}).join(', ');
return Code('return _$publicMethodName($parametersListString);');
}
Expression _getMethodAnnotation(
String requestType,
String path,
bool hasOptionalBody,
) {
return refer(requestType.pascalCase.toUpperCase()).call([literalString(path)],
//{kPath: literalString(path), if (hasOptionalBody) 'optionalBody': refer(true.toString())},
{});
}
String _getCommentsForMethod({
required String methodDescription,
required List<SwaggerRequestParameter> parameters,
required GeneratorOptions options,
}) {
final parametersComments = parameters.map((SwaggerRequestParameter parameter) => _createSummaryParameters(
parameter.name,
parameter.description,
parameter.inParameter,
options,
));
final formattedDescription = methodDescription.split('\n').join('\n///');
return ['///$formattedDescription', ...parametersComments].where((String element) => element.isNotEmpty).join('\n');
}
String _createSummaryParameters(
String parameterName, String parameterDescription, String inParameter, GeneratorOptions options) {
if (inParameter == kHeader && options.ignoreHeaders) {
return '';
}
if (parameterDescription.isNotEmpty) {
parameterDescription = parameterDescription.replaceAll(RegExp(r'\n|\r|\t'), ' ');
} else {
parameterDescription = '';
}
return '///@param $parameterName $parameterDescription';
}
Expression _getParameterAnnotation(SwaggerRequestParameter parameter) {
switch (parameter.inParameter) {
case kFormData:
return refer(kField).call([literalString(parameter.name.replaceAll('\$', ''))]);
case kBody:
return refer(kBody.pascalCase).call([]);
default:
//https://github.com/lejard-h/chopper/issues/295
return refer(parameter.inParameter.pascalCase).call([literalString(parameter.name.replaceAll('\$', ''))]);
}
}
String _getEnumParameterTypeName({
required String parameterName,
required String path,
required String requestType,
}) {
final pathString = path.split('/').map((e) => e.replaceAll('}', '').replaceAll('{', '').pascalCase).join();
final result = '$pathString${requestType.pascalCase}${SwaggerModelsGenerator.getValidatedClassName(parameterName)}';
return result.asEnum();
}
bool _isEnumRefParameter(SwaggerRequestParameter parameter, SwaggerRoot root) {
final schemas = root.components?.schemas ?? {};
schemas.addAll(root.definitions);
final refs = [
parameter.schema?.items?.ref.getRef(),
parameter.schema?.ref.getRef(),
parameter.items?.ref.getRef(),
];
final schema = schemas[refs.firstWhereOrNull((ref) => ref?.isNotEmpty == true)];
if (schema == null) {
return false;
}
if (schema.type == kString && schema.enumValues.isNotEmpty) {
return true;
}
return false;
}
String _getParameterTypeName({
required SwaggerRequestParameter parameter,
required String path,
required String requestType,
required String modelPostfix,
required SwaggerRoot root,
required List<RequestOverrideValueMap> overridenRequests,
}) {
if (parameter.name == 'gender') {
// print(parameter.toJson());
// print(parameter.schema?.toJson());
}
final temp =
overridenRequests.firstWhereOrNull((element) => element.url == path && element.paramName == parameter.name);
if (temp != null) {
return temp.overriddenValue;
}
if (parameter.inParameter == kHeader) {
return _mapParameterName(kString, '');
} else if (parameter.items?.enumValues.isNotEmpty == true || parameter.schema?.enumValues.isNotEmpty == true) {
return _getEnumParameterTypeName(parameterName: parameter.name, path: path, requestType: requestType);
} else if (parameter.items?.type.isNotEmpty == true) {
return _mapParameterName(parameter.items!.type, modelPostfix).asList();
} else if (parameter.items?.ref.isNotEmpty == true) {
if (_isEnumRefParameter(parameter, root)) {
return parameter.items!.ref.getRef().asEnum();
}
return _mapParameterName(parameter.items!.ref.getRef(), modelPostfix).asList();
} else if (parameter.schema?.items?.ref.isNotEmpty == true) {
if (_isEnumRefParameter(parameter, root)) {
return parameter.schema!.items!.ref.getRef().asEnum();
}
return (parameter.schema!.items!.ref.getRef() + modelPostfix).asList();
} else if (parameter.schema?.ref.isNotEmpty == true) {
if (parameter.schema!.ref.toLowerCase().contains('enum')) {
return 'int';
}
if (parameter.schema!.ref.toLowerCase().contains('short')) {
return 'int';
}
if (_isEnumRefParameter(parameter, root)) {
return parameter.schema!.ref.getRef().asEnum();
}
if (parameter.schema!.items != null || parameter.schema!.type == kArray) {
return (parameter.schema!.ref.getRef() + modelPostfix).asList();
}
return (parameter.schema!.ref.getRef() + modelPostfix);
} else if (parameter.schema?.type == kArray && parameter.schema?.items?.type.isNotEmpty == true) {
return _mapParameterName(parameter.schema!.items!.type, '').asList();
} else if (parameter.schema?.anyOf.firstOrNull?.type.isNotEmpty == true) {
return _mapParameterName(parameter.schema!.anyOf.first.type, '');
}
final neededType = parameter.type.isNotEmpty ? parameter.type : parameter.schema?.type ?? kObject.pascalCase;
return _mapParameterName(neededType, modelPostfix);
}
String _mapParameterName(String name, String modelPostfix) {
return kBasicTypesMap[name] ?? name.pascalCase + modelPostfix;
}
List<SwaggerRequestParameter> _getParameter(
List<SwaggerRequestParameter> parameters, bool ignoreHeaders, List<String> excludeParams) {
return parameters
.where((element) => excludeParams.isEmpty || !excludeParams.contains(element.name.toLowerCase()))
.where((swaggerParameter) => ignoreHeaders ? swaggerParameter.inParameter != kHeader : true)
.where((swaggerParameter) => swaggerParameter.inParameter != kCookie)
.where((swaggerParameter) => swaggerParameter.inParameter.isNotEmpty)
.toList();
}
List<Parameter> _getAllParameters({
required SwaggerRequest swaggerRequest,
required bool ignoreHeaders,
required String path,
required String requestType,
required String modelPostfix,
required SwaggerRoot root,
required GeneratorOptions options,
required SwaggerPath swaggerPath,
}) {
final definedParameters = <String, SwaggerRequestParameter>{};
definedParameters.addAll(root.parameters);
definedParameters.addAll(root.components?.parameters ?? {});
var excludeParams = options.excludeParams.map((e) => e.toLowerCase()).toList();
final parameters = [...swaggerRequest.parameters, ...swaggerPath.parameters]
.map((par) => definedParameters[par.ref.split('/').last] ?? par)
.toList();
final overridenRequests = options.requestOverrideValueMap;
;
final result = _getParameter(parameters, ignoreHeaders, excludeParams)
// .where((element) => excludeParams.isEmpty || !excludeParams.contains(element.name.toLowerCase()))
// .where((swaggerParameter) => ignoreHeaders ? swaggerParameter.inParameter != kHeader : true)
// .where((swaggerParameter) => swaggerParameter.inParameter != kCookie)
// .where((swaggerParameter) => swaggerParameter.inParameter.isNotEmpty)
.map(
(swaggerParameter) => Parameter(
(p) => p
..name = swaggerParameter.name.asParameterName()
..named = true
..required = false
..type = Reference(
_getParameterTypeName(
parameter: swaggerParameter,
path: path,
requestType: requestType,
modelPostfix: modelPostfix,
root: root,
overridenRequests: overridenRequests,
), //.makeNullable(),
)
..named = true
..annotations.add(
_getParameterAnnotation(swaggerParameter),
)
..defaultTo = _getHeaderDefaultValue(swaggerParameter, options),
),
)
.toList();
final requestBody = swaggerRequest.requestBody;
if (requestBody != null) {
var typeName = '';
final temp = overridenRequests.firstWhereOrNull((element) => element.url == path && element.paramName == 'body');
if (temp != null) {
typeName = temp.overriddenValue;
} else {
final ref = requestBody.ref;
if (ref.isNotEmpty) {
typeName = ref.getRef();
final requestBodyRef = root.components?.requestBodies[ref.getRef()]?.ref ?? '';
if (requestBodyRef.isNotEmpty == true) {
typeName = requestBodyRef.getRef();
}
typeName = SwaggerModelsGenerator.getValidatedClassName(typeName);
}
final schema = requestBody.content?.schema;
if (schema != null) {
if (schema.format == kBinary) {
typeName = kObject.pascalCase;
} else {
typeName = _getRequestBodyTypeName(
schema: schema,
modelPostfix: options.modelPostfix,
root: root,
);
}
}
}
if (typeName.isNotEmpty) {
result.add(
Parameter(
(p) => p
..name = kBody
..named = true
//..required = true
..type = Reference(typeName //.makeNullable(),
)
..named = true
..annotations.add(
refer(kBody.pascalCase).call([]),
),
),
);
}
}
return result.distinctParameters();
}
bool _isBasicTypeRef(String ref, SwaggerRoot root) {
final schemas = _getAllReusableObjects(root);
final neededSchema = schemas[ref.getUnformattedRef()];
if (neededSchema == null) {
return false;
}
return kBasicTypes.contains(neededSchema.type);
}
bool _isEnumRef(String ref, SwaggerRoot root) {
final schemas = root.components?.schemas ?? <String, SwaggerSchema>{};
schemas.addAll(root.definitions);
final neededSchemaKey = schemas.keys.firstWhereOrNull((key) => key.getRef() == ref.getRef());
if (neededSchemaKey == null) {
return false;
}
final neededSchema = schemas[neededSchemaKey]!;
if (neededSchema.type == kString && neededSchema.enumValues.isNotEmpty) {
return true;
}
return false;
}
String _getRequestBodyTypeName({
required SwaggerSchema schema,
required String modelPostfix,
required SwaggerRoot root,
}) {
if (schema.type.isNotEmpty) {
if (schema.type == kArray) {
final ref = schema.items?.ref.getRef() ?? '';
if (_isEnumRef(ref, root)) {
return ref.asEnum().asList();
}
if (_isBasicTypeRef(ref, root)) {
return kObject.pascalCase;
}
if (ref.isNotEmpty) {
return SwaggerModelsGenerator.getValidatedClassName(ref.withPostfix(modelPostfix)).asList();
}
return '';
}
return kBasicTypesMap[schema.type] ?? schema.type;
}
if (schema.ref.isNotEmpty) {
if (_isEnumRef(schema.ref, root)) {
return schema.ref.getRef().asEnum();
}
if (_isBasicTypeRef(schema.ref, root)) {
return kObject.pascalCase;
}
return SwaggerModelsGenerator.getValidatedClassName(schema.ref.getRef().withPostfix(modelPostfix));
}
return '';
}
Code? _getHeaderDefaultValue(SwaggerRequestParameter swaggerParameter, GeneratorOptions options) {
final overridenValue = options.defaultHeaderValuesMap
.firstWhereOrNull((map) => map.headerName.toLowerCase() == swaggerParameter.name.toLowerCase());
if (overridenValue != null) {
return Code('\'${overridenValue.defaultValue}\'');
}
return null;
}
String _getRequestMethodName({
required SwaggerRequest swaggerRequest,
required GeneratorOptions options,
required String path,
required String requestType,
}) {
return SwaggerModelsGenerator.generateRequestName(path, requestType);
}
static SwaggerResponse? getSuccessedResponse({
required Map<String, SwaggerResponse> responses,
}) {
return responses.entries
.firstWhereOrNull((responseEntry) =>
successResponseCodes.contains(responseEntry.key) ||
successDescriptions.contains(responseEntry.value.description))
?.value;
}
String _getResponseModelName({
required String path,
required String methodName,
required String modelPostfix,
}) {
return '${methodName.pascalCase}\$$kResponse$modelPostfix';
}
String? _getReturnTypeFromType(SwaggerResponse swaggerResponse, String modelPostfix) {
final responseType = swaggerResponse.schema?.type ?? '';
if (responseType.isEmpty) {
return null;
}
if (responseType == kArray) {
final itemsOriginalRef = swaggerResponse.schema?.items?.originalRef;
final itemsType = swaggerResponse.schema?.items?.type;
final itemsRef = swaggerResponse.schema?.items?.ref.getRef();
final arrayType =
[itemsRef, itemsOriginalRef, itemsType, kObject].firstWhere((element) => element?.isNotEmpty == true)!;
final mappedArrayType = kBasicTypesMap[arrayType] ?? arrayType;
if (mappedArrayType.isEmpty) {
return null;
}
return _mapParameterName(mappedArrayType, modelPostfix).asList();
}
return kBasicTypesMap[responseType] ?? responseType + modelPostfix;
}
String? _getReturnTypeFromSchema(SwaggerResponse swaggerResponse, String modelPostfix, SwaggerRoot root) {
final listRef = swaggerResponse.schema?.items?.ref ?? '';
if (listRef.isNotEmpty) {
return (listRef.getRef() + modelPostfix).asList();
}
final ref = swaggerResponse.schema?.ref ?? swaggerResponse.ref;
if (ref.isNotEmpty) {
final allReusableObjects = _getAllReusableObjects(root);
final neededResponse = allReusableObjects[ref.getUnformattedRef()];
if (neededResponse == null) {
return kObject.pascalCase;
}
if (neededResponse.ref.isNotEmpty) {
return kObject.pascalCase;
}
return ref.getRef() + modelPostfix;
}
return null;
}
Map<String, SwaggerSchema> _getAllReusableObjects(SwaggerRoot root) {
final results = <String, SwaggerSchema>{};
results.addAll(root.definitions);
results.addAll(root.components?.schemas ?? {});
results.addAll(root.components?.responses ?? {});
results.addAll(root.components?.requestBodies ?? {});
return results;
}
String? _getReturnTypeFromOriginalRef(SwaggerResponse swaggerResponse, String modelPostfix) {
if (swaggerResponse.schema?.originalRef.isNotEmpty == true) {
return swaggerResponse.schema!.originalRef + modelPostfix;
}
return null;
}
String? _getReturnTypeFromContent({
required SwaggerResponse swaggerResponse,
required String modelPostfix,
required SwaggerRoot swaggerRoot,
}) {
final content = swaggerResponse.content;
if (content == null) {
return null;
}
final ref = content.ref;
if (ref.isNotEmpty) {
final type = ref.getRef().withPostfix(modelPostfix);
return kBasicTypesMap[type] ?? type;
}
final schemaRef = content.schema?.ref ?? '';
if (schemaRef.isNotEmpty) {
final allRefs = _getAllReusableObjects(swaggerRoot);
final neededSchema = allRefs[schemaRef.getUnformattedRef()];
if (neededSchema == null) {
return kObject.pascalCase;
}
if (kBasicTypes.contains(neededSchema.type)) {
return kObject.pascalCase;
}
final typeName = SwaggerModelsGenerator.getValidatedClassName(schemaRef.getRef()).withPostfix(modelPostfix);
if (neededSchema.type == kArray) {
return neededSchema.items?.ref.getRef().withPostfix(modelPostfix).asList();
}
return typeName;
}
final responseType = content.responseType;
if (responseType.isNotEmpty) {
if (responseType == kArray) {
final originalRef = swaggerResponse.schema?.items?.originalRef ?? '';
if (originalRef.isNotEmpty) {
return kBasicTypesMap[originalRef]?.asList();
}
}
}
final itemsRef = content.items?.ref ?? '';
if (itemsRef.isNotEmpty) {
return kBasicTypesMap[itemsRef]?.withPostfix(modelPostfix).asList();
}
final schemaItemsRef = content.schema?.items?.ref ?? '';
if (schemaItemsRef.isNotEmpty) {
final result =
SwaggerModelsGenerator.getValidatedClassName(schemaItemsRef.getRef()).withPostfix(modelPostfix).asList();
return result;
}
final contentSchemaType = content.schema?.type ?? '';
if (contentSchemaType.isNotEmpty == true) {
return kBasicTypesMap[contentSchemaType];
}
if (responseType.isEmpty) {
return '';
}
return kBasicTypesMap[responseType] ?? responseType + modelPostfix;
}
String _getReturnTypeName({
required Map<String, SwaggerResponse> responses,
required Map<String, ResponseOverrideValueMap> overridenResponses,
required String path,
required String methodName,
required String modelPostfix,
required SwaggerRoot swaggerRoot,
}) {
if (overridenResponses.containsKey(path)) {
return overridenResponses[path]!.overriddenValue;
}
final neededResponse = getSuccessedResponse(
responses: responses,
);
if (neededResponse == null) {
return '';
}
if (neededResponse.schema?.type == kObject && neededResponse.schema?.properties.isNotEmpty == true) {
return _getResponseModelName(
path: path,
methodName: methodName,
modelPostfix: modelPostfix,
);
}
final type = _getReturnTypeFromType(neededResponse, modelPostfix) ??
_getReturnTypeFromSchema(neededResponse, modelPostfix, swaggerRoot) ??
_getReturnTypeFromOriginalRef(neededResponse, modelPostfix) ??
_getReturnTypeFromContent(
swaggerResponse: neededResponse,
modelPostfix: modelPostfix,
swaggerRoot: swaggerRoot,
) ??
'';
if (type.isNotEmpty) {
return type;
}
return '';
}
}

View File

@ -0,0 +1,13 @@
import 'dart:convert';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
class SwaggerEnumsGeneratorV2 extends SwaggerEnumsGenerator {
@override
String generate(String dartCode, String fileName) {
final dynamic map = jsonDecode(dartCode);
final definitions = map['definitions'] as Map<String, dynamic>? ?? {};
return generateFromMap(dartCode, fileName, definitions, {}, {});
}
}

View File

@ -0,0 +1,102 @@
import 'dart:convert';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.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/models/generator_options.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
class SwaggerModelsGeneratorV2 extends SwaggerModelsGenerator {
@override
String generate(String dartCode, String fileName, GeneratorOptions options, Map<String, dynamic> requestClass) {
final dynamic map = jsonDecode(dartCode);
final definitions = map['definitions'] as Map<String, dynamic>?;
return generateBase(dartCode, fileName, options, definitions ?? {}, true, requestClass);
}
@override
String generateResponses(String dartCode, String fileName, GeneratorOptions options) {
return '';
}
@override
String generateRequestBodies(String dartCode, String fileName, GeneratorOptions options) {
return '';
}
@override
List<String> getAllEnumNames(String swaggerFile) {
final results = SwaggerEnumsGenerator.getEnumNamesFromRequests(swaggerFile);
final swagger = jsonDecode(swaggerFile);
final definitions = swagger['definitions'] as Map<String, dynamic>? ?? {};
if (definitions.isNotEmpty) {
definitions.forEach((className, map) {
final mapMap = map as Map<String, dynamic>;
if (mapMap.containsKey('enum')) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
if (mapMap['type'] == 'array' && mapMap['items'] != null && mapMap['items']['enum'] != null) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
final properties = map['properties'] as Map<String, dynamic>?;
if (properties == null) {
return;
}
properties.forEach((propertyName, propertyValue) {
var property = propertyValue as Map<String, dynamic>;
if (property.containsKey('enum') || (property['items'] != null && property['items']['enum'] != null)) {
results.add(SwaggerEnumsGeneratorV2()
.generateEnumName(SwaggerModelsGenerator.getValidatedClassName(className), propertyName));
}
});
});
}
final resultsWithPrefix = results.map((element) {
return 'enums.$element';
}).toList();
return resultsWithPrefix;
}
@override
List<String> getAllListEnumNames(String swaggerFile) {
final results = SwaggerEnumsGenerator.getEnumNamesFromRequests(swaggerFile);
final swagger = jsonDecode(swaggerFile);
final definitions = swagger['definitions'] as Map<String, dynamic>?;
if (definitions != null) {
definitions.forEach((className, map) {
final mapMap = map as Map<String, dynamic>;
if (mapMap['type'] == 'array' && mapMap['items'] != null && mapMap['items']['enum'] != null) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
});
}
final resultsWithPrefix = results.map((element) {
return 'enums.$element';
}).toList();
return resultsWithPrefix;
}
@override
String getExtendsString(Map<String, dynamic> map) {
return '';
}
}

View File

@ -0,0 +1,25 @@
import 'dart:convert';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
class SwaggerEnumsGeneratorV3 extends SwaggerEnumsGenerator {
@override
String generate(String dartCode, String fileName) {
final dynamic map = jsonDecode(dartCode);
final components = map['components'] as Map<String, dynamic>?;
final schemas = components == null
? null
: components['schemas'] as Map<String, dynamic>?;
final responses = components == null
? null
: components['responses'] as Map<String, dynamic>?;
final requestBodies = components == null
? null
: components['requestBodies'] as Map<String, dynamic>?;
return generateFromMap(dartCode, fileName, schemas ?? {}, responses ?? {},
requestBodies ?? {});
}
}

View File

@ -0,0 +1,256 @@
import 'dart:convert';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v3/swagger_enums_generator_v3.dart';
import 'package:swagger_dart_code_generator/src/extensions/string_extension.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:collection/collection.dart';
class SwaggerModelsGeneratorV3 extends SwaggerModelsGenerator {
@override
String generate(String dartCode, String fileName, GeneratorOptions options, Map<String, dynamic> requestClass) {
final dynamic map = jsonDecode(dartCode);
final components = map['components'] as Map<String, dynamic>?;
final schemas = components == null ? null : components['schemas'] as Map<String, dynamic>?;
return generateBase(dartCode, fileName, options, schemas ?? {}, true, requestClass);
}
@override
String generateResponses(String dartCode, String fileName, GeneratorOptions options) {
final dynamic map = jsonDecode(dartCode);
final components = map['components'] as Map<String, dynamic>?;
final responses = components == null ? null : components['responses'] as Map<String, dynamic>?;
if (responses == null) {
return '';
}
var result = <String, dynamic>{};
final allModelNames = components!.containsKey('schemas')
? (components['schemas'] as Map<String, dynamic>)
.keys
.map((e) => SwaggerModelsGenerator.getValidatedClassName(e))
: <String>[];
responses.keys.forEach((key) {
if (!allModelNames.contains(key)) {
final response = responses[key] as Map<String, dynamic>?;
final content = response == null ? null : response['content'] as Map<String, dynamic>?;
final firstContent = content == null ? null : content.entries.firstOrNull?.value as Map<String, dynamic>?;
final schema = firstContent == null ? null : firstContent['schema'];
if (schema != null && schema['\$ref'] == null) {
result.addAll({key: schema});
}
}
});
return generateBase(dartCode, fileName, options, result, false, {});
}
@override
String generateRequestBodies(String dartCode, String fileName, GeneratorOptions options) {
final dynamic map = jsonDecode(dartCode);
final components = map['components'] as Map<String, dynamic>?;
final requestBodies = components == null ? null : components['requestBodies'] as Map<String, dynamic>?;
if (requestBodies == null) {
return '';
}
var result = <String, dynamic>{};
final allModelNames = components!.containsKey('schemas')
? (components['schemas'] as Map<String, dynamic>)
.keys
.map((e) => SwaggerModelsGenerator.getValidatedClassName(e))
: <String>[];
requestBodies.keys.forEach((key) {
if (!allModelNames.contains(key)) {
final response = requestBodies[key] as Map<String, dynamic>?;
final content = response == null ? null : response['content'] as Map<String, dynamic>;
final firstContent = content == null ? null : content.entries.firstOrNull?.value as Map<String, dynamic>?;
final schema = firstContent == null ? null : firstContent['schema'];
if (schema != null) {
result.addAll({key: schema});
}
}
});
return generateBase(dartCode, fileName, options, result, false, {});
}
@override
List<String> getAllEnumNames(String swaggerFile) {
final results = SwaggerEnumsGenerator.getEnumNamesFromRequests(swaggerFile);
final swagger = jsonDecode(swaggerFile);
final components = swagger['components'] as Map<String, dynamic>?;
final schemas = components == null ? null : components['schemas'] as Map<String, dynamic>?;
final responses = components == null ? null : components['responses'] as Map<String, dynamic>?;
final requestBodies = components == null ? null : components['requestBodies'] as Map<String, dynamic>?;
if (schemas != null) {
schemas.forEach((className, map) {
final mapMap = map as Map<String, dynamic>;
if (mapMap.containsKey('enum')) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
if (mapMap['type'] == 'array' && mapMap['items'] != null && mapMap['items']['enum'] != null) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
Map<String, dynamic>? properties;
if (mapMap.containsKey('allOf')) {
final allOf = mapMap['allOf'] as List<dynamic>;
var propertiesContainer = allOf.firstWhereOrNull((e) => (e as Map<String, dynamic>).containsKey('properties'))
as Map<String, dynamic>?;
if (propertiesContainer != null) {
properties = propertiesContainer['properties'] as Map<String, dynamic>?;
} else {
properties = map['properties'] as Map<String, dynamic>?;
}
} else {
properties = map['properties'] as Map<String, dynamic>?;
}
if (properties == null) {
return;
}
properties.forEach((propertyName, propertyValue) {
var property = propertyValue as Map<String, dynamic>;
if (property.containsKey('enum') || (property['items'] != null && property['items']['enum'] != null)) {
results.add(SwaggerModelsGenerator.getValidatedClassName(SwaggerEnumsGeneratorV3()
.generateEnumName(SwaggerModelsGenerator.getValidatedClassName(className), propertyName)));
}
});
});
}
if (responses != null) {
responses.forEach((className, map) {
final response = responses[className];
final content = response['content'] as Map<String, dynamic>?;
final firstContent = content?.entries.firstOrNull?.value;
final schema = firstContent == null ? null : firstContent['schema'];
if (schema != null && (schema as Map<String, dynamic>).containsKey('enum')) {
results.add(className.capitalize);
return;
}
final properties = schema == null ? null : schema['properties'] as Map<String, dynamic>?;
if (properties == null) {
return;
}
properties.forEach((propertyName, propertyValue) {
var property = propertyValue as Map<String, dynamic>;
if (property.containsKey('enum') || (property['items'] != null && property['items']['enum'] != null)) {
results.add(SwaggerEnumsGeneratorV3().generateEnumName(className, propertyName));
}
});
});
}
if (requestBodies != null) {
requestBodies.forEach((className, map) {
final response = requestBodies[className];
final content = response['content'] as Map<String, dynamic>;
final firstContent = content.entries.firstOrNull?.value;
final schema = firstContent == null ? null : firstContent['schema'];
if (schema != null && (schema as Map<String, dynamic>).containsKey('enum')) {
results.add(className.capitalize);
return;
}
final properties = schema == null ? null : schema['properties'] as Map<String, dynamic>?;
if (properties == null) {
return;
}
properties.forEach((propertyName, propertyValue) {
var property = propertyValue as Map<String, dynamic>;
if (property.containsKey('enum') || (property['items'] != null && property['items']['enum'] != null)) {
results.add(SwaggerEnumsGeneratorV3().generateEnumName(className, propertyName));
}
});
});
}
final resultsWithPrefix = results.map((element) {
return 'enums.$element';
}).toList();
return resultsWithPrefix;
}
@override
List<String> getAllListEnumNames(String swaggerFile) {
final results = SwaggerEnumsGenerator.getEnumNamesFromRequests(swaggerFile);
final swagger = jsonDecode(swaggerFile);
final components = swagger['components'] as Map<String, dynamic>?;
final schemas = components == null ? null : components['schemas'] as Map<String, dynamic>?;
if (schemas != null) {
schemas.forEach((className, map) {
final mapMap = map as Map<String, dynamic>;
if (mapMap['type'] == 'array' && mapMap['items'] != null && mapMap['items']['enum'] != null) {
results.add(SwaggerModelsGenerator.getValidatedClassName(className.capitalize));
return;
}
});
}
final resultsWithPrefix = results.map((element) {
return 'enums.$element';
}).toList();
return resultsWithPrefix;
}
@override
String getExtendsString(Map<String, dynamic> map) {
if (map.containsKey('allOf')) {
final allOf = map['allOf'] as List<dynamic>;
final refItem = allOf.firstWhere((m) => (m as Map<String, dynamic>).containsKey('\$ref'));
final ref = refItem['\$ref'].toString().split('/').last;
final className = SwaggerModelsGenerator.getValidatedClassName(ref);
return 'extends $className';
}
return '';
}
}

View File

@ -0,0 +1 @@
const String converterClassEnding = 'JsonDecoderMappings';

View File

@ -0,0 +1,57 @@
/// List of all exception words in Dart language
List<String> exceptionWords = <String>[
'abstract',
'continue',
'false',
'new',
'this',
'as',
'default',
'final',
'null',
'throw',
'assert',
'deferred',
'finnaly',
'operator',
'true',
'async',
'dynamic',
'get',
'rethrow',
'typedef',
'await',
'else',
'if',
'return',
'var',
'break',
'enum',
'implements',
'set',
'void',
'case',
'export',
'import',
'static',
'while',
'catch',
'external',
'in',
'super',
'with',
'class',
'extends',
'is',
'switch',
'yield',
'const',
'factory',
'library',
'sync',
'do',
'for',
'part',
'try',
'client',
];

View File

@ -0,0 +1,19 @@
import 'package:swagger_dart_code_generator/src/extensions/string_extension.dart';
String getClassNameFromFileName(String file) {
final name = file.split('.').first.replaceAll('-', '_');
final result = name.split('_').map((String e) => e.capitalize);
return result.join();
}
String getFileNameWithoutExtension(String file) {
return file.split('.').first;
}
String getFileNameBase(String filePath) {
final fileName = filePath.split('/').last.replaceAll('-', '_');
final lastDot = fileName.lastIndexOf('.');
return fileName.substring(0, lastDot);
}

View File

@ -0,0 +1,42 @@
import 'package:code_builder/code_builder.dart';
extension ParameterExtension on Parameter {
Parameter copyWith({
Reference? type,
List<Expression>? annotations,
String? name,
}) =>
Parameter(
(p) => p
..name = name ?? this.name
..named = named
..required = required
..type = type ?? this.type
..named = named
..defaultTo = defaultTo
..annotations.addAll(annotations ?? this.annotations),
);
}
extension ParameterListExtension on List<Parameter> {
List<Parameter> distinctParameters() {
final allParameterNames = <String>[];
final results = <Parameter>[];
for (var element in this) {
if (allParameterNames.contains(element.name)) {
var newName = element.name;
while (allParameterNames.contains(newName)) {
newName += '\$';
}
allParameterNames.add(newName);
results.add(element.copyWith(name: newName));
} else {
allParameterNames.add(element.name);
results.add(element);
}
}
return results;
}
}

View File

@ -0,0 +1,52 @@
import 'package:recase/recase.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
extension CapitalizeExtension on String {
String get capitalize {
return isEmpty ? this : (this[0].toUpperCase() + substring(1));
}
String get lower {
return isEmpty ? this : (this[0].toLowerCase() + substring(1));
}
bool get isUpper {
return this == toUpperCase() && this != toLowerCase();
}
}
extension TypeExtension on String {
String makeNullable() {
if (endsWith('?')) {
return this;
}
return '$this?';
}
String getRef() => split('/').last.pascalCase;
String getUnformattedRef() => split('/').last;
String withPostfix(String postfix) => '${this}$postfix';
String asList() => 'List<$this>';
String asEnum() => 'enums.$this';
String asFutureResponse() => 'Future<$this>';
String asParameterName() {
return SwaggerModelsGenerator.getValidatedParameterName(this);
}
String asParameterType() {
if (isEmpty) {
return 'dynamic';
}
final result = split('-').map((String str) => str == str.capitalize).toList().join();
return result;
}
}

View File

@ -0,0 +1,204 @@
import 'package:json_annotation/json_annotation.dart';
part 'generator_options.g2.dart';
@JsonSerializable(fieldRename: FieldRename.snake, anyMap: true)
class GeneratorOptions {
/// Instantiate generator options.
GeneratorOptions({
this.withBaseUrl = true,
this.withConverter = true,
this.ignoreHeaders = false,
this.separateModels = false,
this.useDefaultNullForLists = false,
this.buildOnlyModels = false,
this.defaultValuesMap = const <DefaultValueMap>[],
this.defaultHeaderValuesMap = const <DefaultHeaderValueMap>[],
this.responseOverrideValueMap = const <ResponseOverrideValueMap>[],
required this.inputFolder,
required this.outputFolder,
this.enumsCaseSensitive = true,
this.useRequiredAttributeForHeaders = true,
this.useInheritance = true,
this.includeIfNull,
this.modelPostfix = '',
this.includePaths = const [],
this.excludePaths = const [],
this.excludeParams = const [],
this.defaultApiVersion = '1.0',
this.customApiVersion = const <CustomApiVersion>[],
this.urlParterns = const [],
this.requestOverrideValueMap = const <RequestOverrideValueMap>[],
this.customModelPath = const [],
});
/// Build options from a JSON map.
factory GeneratorOptions.fromJson(Map<String, dynamic> json) => _$GeneratorOptionsFromJson(json);
@JsonKey(defaultValue: true)
final bool withBaseUrl;
@JsonKey(defaultValue: true)
final bool withConverter;
@JsonKey(defaultValue: false)
final bool separateModels;
@JsonKey(defaultValue: true)
final bool useRequiredAttributeForHeaders;
@JsonKey(defaultValue: false)
final bool ignoreHeaders;
@JsonKey(defaultValue: true)
final bool useInheritance;
@JsonKey(defaultValue: false)
final bool enumsCaseSensitive;
@JsonKey(defaultValue: null)
final bool? includeIfNull;
@JsonKey(defaultValue: '')
final String inputFolder;
@JsonKey(defaultValue: '')
final String outputFolder;
@JsonKey(defaultValue: false)
final bool useDefaultNullForLists;
@JsonKey(defaultValue: false)
final bool buildOnlyModels;
@JsonKey(defaultValue: '')
final String modelPostfix;
@JsonKey(defaultValue: <DefaultValueMap>[])
final List<DefaultValueMap> defaultValuesMap;
@JsonKey(defaultValue: <DefaultHeaderValueMap>[])
final List<DefaultHeaderValueMap> defaultHeaderValuesMap;
@JsonKey(defaultValue: <ResponseOverrideValueMap>[])
final List<ResponseOverrideValueMap> responseOverrideValueMap;
@JsonKey(defaultValue: [])
final List<String> includePaths;
@JsonKey(defaultValue: [])
final List<String> excludePaths;
@JsonKey(defaultValue: [])
final List<String> excludeParams;
@JsonKey(defaultValue: '1.0')
final String defaultApiVersion;
@JsonKey(defaultValue: [])
final List<CustomApiVersion> customApiVersion;
@JsonKey(defaultValue: '')
final List<String> urlParterns;
@JsonKey(defaultValue: <RequestOverrideValueMap>[])
final List<RequestOverrideValueMap> requestOverrideValueMap;
@JsonKey(defaultValue: '')
final List<String> customModelPath;
/// Convert this options instance to JSON.
Map<String, dynamic> toJson() => _$GeneratorOptionsToJson(this);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class DefaultValueMap {
DefaultValueMap({required this.typeName, required this.defaultValue});
/// Build a default value map from a JSON map.
factory DefaultValueMap.fromJson(Map<String, dynamic> json) => _$DefaultValueMapFromJson(json);
@JsonKey(defaultValue: '')
final String typeName;
@JsonKey(defaultValue: '')
final String defaultValue;
/// Convert this default value map instance to JSON.
Map<String, dynamic> toJson() => _$DefaultValueMapToJson(this);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class ResponseOverrideValueMap {
ResponseOverrideValueMap({required this.url, required this.method, required this.overriddenValue});
/// Build a default value map from a JSON map.
factory ResponseOverrideValueMap.fromJson(Map<String, dynamic> json) => _$ResponseOverrideValueMapFromJson(json);
@JsonKey(defaultValue: '')
final String url;
@JsonKey(defaultValue: '')
final String method;
@JsonKey(defaultValue: '')
final String overriddenValue;
/// Convert this default value map instance to JSON.
Map<String, dynamic> toJson() => _$ResponseOverrideValueMapToJson(this);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class RequestOverrideValueMap {
RequestOverrideValueMap(
{required this.url, required this.method, required this.overriddenValue, required this.paramName});
/// Build a default value map from a JSON map.
factory RequestOverrideValueMap.fromJson(Map<String, dynamic> json) => _$RequestOverrideValueMapFromJson(json);
@JsonKey(defaultValue: '')
final String url;
@JsonKey(defaultValue: '')
final String paramName;
@JsonKey(defaultValue: '')
final String method;
@JsonKey(defaultValue: '')
final String overriddenValue;
/// Convert this default value map instance to JSON.
Map<String, dynamic> toJson() => _$RequestOverrideValueMapToJson(this);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class CustomApiVersion {
CustomApiVersion({required this.version, required this.urls});
/// Build a default value map from a JSON map.
factory CustomApiVersion.fromJson(Map<String, dynamic> json) => _$CustomApiVersionFromJson(json);
@JsonKey(defaultValue: '')
final String version;
@JsonKey(defaultValue: [])
final List<String> urls;
/// Convert this default value map instance to JSON.
Map<String, dynamic> toJson() => _$CustomApiVersionToJson(this);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class DefaultHeaderValueMap {
DefaultHeaderValueMap({required this.headerName, required this.defaultValue});
@JsonKey(defaultValue: '')
final String headerName;
@JsonKey(defaultValue: '')
final String defaultValue;
Map<String, dynamic> toJson() => _$DefaultHeaderValueMapToJson(this);
factory DefaultHeaderValueMap.fromJson(Map<String, dynamic> json) => _$DefaultHeaderValueMapFromJson(json);
}

View File

@ -0,0 +1,131 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'generator_options.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GeneratorOptions _$GeneratorOptionsFromJson(Map json) => GeneratorOptions(
withBaseUrl: json['with_base_url'] as bool? ?? true,
withConverter: json['with_converter'] as bool? ?? true,
ignoreHeaders: json['ignore_headers'] as bool? ?? false,
separateModels: json['separate_models'] as bool? ?? false,
useDefaultNullForLists: json['use_default_null_for_lists'] as bool? ?? false,
buildOnlyModels: json['build_only_models'] as bool? ?? false,
defaultValuesMap: (json['default_values_map'] as List<dynamic>?)
?.map((e) => DefaultValueMap.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
defaultHeaderValuesMap: (json['default_header_values_map'] as List<dynamic>?)
?.map((e) => DefaultHeaderValueMap.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
responseOverrideValueMap: (json['response_override_value_map'] as List<dynamic>?)
?.map((e) => ResponseOverrideValueMap.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
inputFolder: json['input_folder'] as String? ?? '',
outputFolder: json['output_folder'] as String? ?? '',
enumsCaseSensitive: json['enums_case_sensitive'] as bool? ?? false,
useRequiredAttributeForHeaders: json['use_required_attribute_for_headers'] as bool? ?? true,
useInheritance: json['use_inheritance'] as bool? ?? true,
includeIfNull: json['include_if_null'] as bool?,
modelPostfix: json['model_postfix'] as String? ?? '',
includePaths: (json['include_paths'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
excludePaths: (json['exclude_paths'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
excludeParams: (json['exclude_params'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
defaultApiVersion: json['default_api_version'] as String? ?? '1.0',
customApiVersion: (json['custom_api_version'] as List<dynamic>?)
?.map((e) => CustomApiVersion.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
urlParterns: (json['url_parterns'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
requestOverrideValueMap: (json['request_override_value_map'] as List<dynamic>?)
?.map((e) => RequestOverrideValueMap.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
customModelPath: (json['custom_model_path'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
);
Map<String, dynamic> _$GeneratorOptionsToJson(GeneratorOptions instance) => <String, dynamic>{
'with_base_url': instance.withBaseUrl,
'with_converter': instance.withConverter,
'separate_models': instance.separateModels,
'use_required_attribute_for_headers': instance.useRequiredAttributeForHeaders,
'ignore_headers': instance.ignoreHeaders,
'use_inheritance': instance.useInheritance,
'enums_case_sensitive': instance.enumsCaseSensitive,
'include_if_null': instance.includeIfNull,
'input_folder': instance.inputFolder,
'output_folder': instance.outputFolder,
'use_default_null_for_lists': instance.useDefaultNullForLists,
'build_only_models': instance.buildOnlyModels,
'model_postfix': instance.modelPostfix,
'default_values_map': instance.defaultValuesMap,
'default_header_values_map': instance.defaultHeaderValuesMap,
'response_override_value_map': instance.responseOverrideValueMap,
'include_paths': instance.includePaths,
'exclude_paths': instance.excludePaths,
'exclude_params': instance.excludeParams,
'default_api_version': instance.defaultApiVersion,
'url_parterns': instance.urlParterns,
};
DefaultValueMap _$DefaultValueMapFromJson(Map<String, dynamic> json) => DefaultValueMap(
typeName: json['type_name'] as String? ?? '',
defaultValue: json['default_value'] as String? ?? '',
);
Map<String, dynamic> _$DefaultValueMapToJson(DefaultValueMap instance) => <String, dynamic>{
'type_name': instance.typeName,
'default_value': instance.defaultValue,
};
ResponseOverrideValueMap _$ResponseOverrideValueMapFromJson(Map<String, dynamic> json) => ResponseOverrideValueMap(
url: json['url'] as String? ?? '',
method: json['method'] as String? ?? '',
overriddenValue: json['overridden_value'] as String? ?? '',
);
Map<String, dynamic> _$ResponseOverrideValueMapToJson(ResponseOverrideValueMap instance) => <String, dynamic>{
'url': instance.url,
'method': instance.method,
'overridden_value': instance.overriddenValue,
};
RequestOverrideValueMap _$RequestOverrideValueMapFromJson(Map<String, dynamic> json) => RequestOverrideValueMap(
url: json['url'] as String? ?? '',
method: json['method'] as String? ?? '',
overriddenValue: json['overridden_value'] as String? ?? '',
paramName: json['param_name'] as String? ?? '',
);
Map<String, dynamic> _$RequestOverrideValueMapToJson(RequestOverrideValueMap instance) => <String, dynamic>{
'url': instance.url,
'method': instance.method,
'overridden_value': instance.overriddenValue,
'param_name': instance.paramName,
};
DefaultHeaderValueMap _$DefaultHeaderValueMapFromJson(Map<String, dynamic> json) => DefaultHeaderValueMap(
headerName: json['header_name'] as String? ?? '',
defaultValue: json['default_value'] as String? ?? '',
);
Map<String, dynamic> _$DefaultHeaderValueMapToJson(DefaultHeaderValueMap instance) => <String, dynamic>{
'header_name': instance.headerName,
'default_value': instance.defaultValue,
};
CustomApiVersion _$CustomApiVersionFromJson(Map<String, dynamic> json) => CustomApiVersion(
version: json['version'] as String? ?? '',
urls: json['urls'] != null
? (json['urls'].toString().split(',').where((element) => element.isNotEmpty).toList())
: <String>[],
);
Map<String, dynamic> _$CustomApiVersionToJson(CustomApiVersion instance) => <String, dynamic>{
'version': instance.version,
'urls': instance.urls,
};

View File

@ -0,0 +1,90 @@
import 'dart:convert';
import 'package:code_builder/code_builder.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_additions_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_converter_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/swagger_requests_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v2/swagger_enums_generator_v2.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v2/swagger_models_generator_v2.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v3/swagger_enums_generator_v3.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v3/swagger_models_generator_v3.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
class SwaggerCodeGenerator {
final Map<int, SwaggerEnumsGenerator> _enumsMap = <int, SwaggerEnumsGenerator>{
2: SwaggerEnumsGeneratorV2(),
3: SwaggerEnumsGeneratorV3()
};
final Map<int, SwaggerModelsGenerator> _modelsMap = <int, SwaggerModelsGenerator>{
2: SwaggerModelsGeneratorV2(),
3: SwaggerModelsGeneratorV3()
};
int _getApiVersion(String dartCode) {
final dynamic map = jsonDecode(dartCode);
final openApi = map['openapi'] as String?;
return openApi != null ? 3 : 2;
}
String generateIndexes(String dartCode, Map<String, List<String>> buildExtensions, GeneratorOptions options) =>
_getSwaggerAdditionsGenerator(dartCode, options).generateIndexes(buildExtensions);
String generateConverterMappings(
String dartCode, Map<String, List<String>> buildExtensions, bool hasModels, GeneratorOptions options) =>
_getSwaggerAdditionsGenerator(dartCode, options).generateConverterMappings(buildExtensions, hasModels, options);
String generateImportsContent(
String dartCode,
String swaggerFileName,
bool hasModels,
bool buildOnlyModels,
bool hasEnums,
bool separateModels,
GeneratorOptions options,
) =>
_getSwaggerAdditionsGenerator(dartCode, options).generateImportsContent(
swaggerFileName, hasModels, buildOnlyModels, hasEnums, separateModels, options.customModelPath);
String generateConverter(String dartCode, String fileName, GeneratorOptions options) =>
_getSwaggerConverterGenerator(dartCode).generate(dartCode, fileName, options);
String generateResponses(String dartCode, String fileName, GeneratorOptions options) =>
_getSwaggerModelsGenerator(dartCode).generateResponses(dartCode, fileName, options);
String generateRequestBodies(String dartCode, String fileName, GeneratorOptions options) =>
_getSwaggerModelsGenerator(dartCode).generateRequestBodies(dartCode, fileName, options);
String generateEnums(String dartCode, String fileName) =>
_getSwaggerEnumsGenerator(dartCode).generate(dartCode, fileName);
String generateModels(
String dartCode, String fileName, GeneratorOptions options, Map<String, dynamic> requestClass) =>
_getSwaggerModelsGenerator(dartCode).generate(dartCode, fileName, options, requestClass);
String generateRequests(String dartCode, String className, String fileName, GeneratorOptions options,
Map<String, dynamic> requestClass) =>
_getSwaggerRequestsGenerator(dartCode).generate(
code: dartCode, className: className, fileName: fileName, options: options, requestClass: requestClass);
String generateCustomJsonConverter(String dartCode, String fileName, GeneratorOptions options) =>
_getSwaggerAdditionsGenerator(dartCode, options).generateCustomJsonConverter(fileName, options);
String generateDateToJson(String dartCode, GeneratorOptions options) =>
_getSwaggerAdditionsGenerator(dartCode, options).generateDateToJson();
SwaggerAdditionsGenerator _getSwaggerAdditionsGenerator(String dartCode, GeneratorOptions options) =>
SwaggerAdditionsGenerator();
SwaggerConverterGenerator _getSwaggerConverterGenerator(String dartCode) => SwaggerConverterGenerator();
SwaggerEnumsGenerator _getSwaggerEnumsGenerator(String dartCode) => _enumsMap[_getApiVersion(dartCode)]!;
SwaggerModelsGenerator _getSwaggerModelsGenerator(String dartCode) => _modelsMap[_getApiVersion(dartCode)]!;
SwaggerRequestsGenerator _getSwaggerRequestsGenerator(String dartCode) => SwaggerRequestsGenerator();
}

View File

@ -0,0 +1,23 @@
import 'package:json_annotation/json_annotation.dart';
part 'parameter_item.g2.dart';
@JsonSerializable()
class ParameterItem {
ParameterItem(
{this.type = '', this.enumValues = const [], this.defaultValue = ''});
factory ParameterItem.fromJson(Map<String, dynamic> json) =>
_$ParameterItemFromJson(json);
@JsonKey(name: 'type', defaultValue: '')
String type;
@JsonKey(name: 'enum', defaultValue: [])
List<String> enumValues;
@JsonKey(name: 'default', defaultValue: '')
String defaultValue;
Map<String, dynamic> toJson() => _$ParameterItemToJson(this);
}

View File

@ -0,0 +1,24 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'parameter_item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
ParameterItem _$ParameterItemFromJson(Map<String, dynamic> json) {
return ParameterItem(
type: json['type'] as String? ?? '',
enumValues:
(json['enum'] as List<dynamic>?)?.map((e) => e as String).toList() ??
[],
defaultValue: json['default'] as String? ?? '',
);
}
Map<String, dynamic> _$ParameterItemToJson(ParameterItem instance) =>
<String, dynamic>{
'type': instance.type,
'enum': instance.enumValues,
'default': instance.defaultValue,
};

View File

@ -0,0 +1,94 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
import '../responses/swagger_response.dart';
import 'swagger_request_parameter.dart';
part 'swagger_request.g2.dart';
@JsonSerializable()
class SwaggerRequest {
SwaggerRequest({
this.summary = '',
this.description = '',
this.operationId = '',
this.consumes = const [],
this.responses = const {},
this.parameters = const [],
this.produces = const [],
this.requestBody,
});
@JsonKey(name: 'summary', defaultValue: '')
String summary;
@JsonKey(name: 'description', defaultValue: '')
String description;
@JsonKey(name: 'operationId', defaultValue: '')
String operationId;
@JsonKey(name: 'consumes', defaultValue: [])
List<String> consumes;
@JsonKey(name: 'produces', defaultValue: [])
List<String> produces;
@JsonKey(name: 'responses', defaultValue: {})
Map<String, SwaggerResponse> responses;
@JsonKey(name: 'parameters', defaultValue: [])
List<SwaggerRequestParameter> parameters;
@JsonKey(name: 'requestBody')
RequestBody? requestBody;
Map<String, dynamic> toJson() => _$SwaggerRequestToJson(this);
factory SwaggerRequest.fromJson(Map<String, dynamic> json) =>
_$SwaggerRequestFromJson(json);
}
@JsonSerializable()
class RequestBody {
@JsonKey(name: 'content', fromJson: _contentFromJson)
RequestContent? content;
@JsonKey(name: '\$ref', defaultValue: '')
String ref;
RequestBody({
this.content,
this.ref = '',
});
Map<String, dynamic> toJson() => _$RequestBodyToJson(this);
factory RequestBody.fromJson(Map<String, dynamic> json) =>
_$RequestBodyFromJson(json);
}
RequestContent? _contentFromJson(Map<String, dynamic>? map) {
if (map == null || map.isEmpty) {
return null;
}
final content = map.values.first as Map<String, dynamic>;
return RequestContent.fromJson(content);
}
@JsonSerializable()
class RequestContent {
RequestContent({
this.schema,
});
@JsonKey(name: 'schema')
final SwaggerSchema? schema;
Map<String, dynamic> toJson() => _$RequestContentToJson(this);
factory RequestContent.fromJson(Map<String, dynamic> json) =>
_$RequestContentFromJson(json);
}

View File

@ -0,0 +1,74 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_request.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerRequest _$SwaggerRequestFromJson(Map<String, dynamic> json) {
return SwaggerRequest(
summary: json['summary'] as String? ?? '',
description: json['description'] as String? ?? '',
operationId: json['operationId'] as String? ?? '',
consumes: (json['consumes'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
[],
responses: (json['responses'] as Map<String, dynamic>?)?.map(
(k, e) =>
MapEntry(k, SwaggerResponse.fromJson(e as Map<String, dynamic>)),
) ??
{},
parameters: (json['parameters'] as List<dynamic>?)
?.map((e) =>
SwaggerRequestParameter.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
produces: (json['produces'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
[],
requestBody: json['requestBody'] == null
? null
: RequestBody.fromJson(json['requestBody'] as Map<String, dynamic>),
);
}
Map<String, dynamic> _$SwaggerRequestToJson(SwaggerRequest instance) =>
<String, dynamic>{
'summary': instance.summary,
'description': instance.description,
'operationId': instance.operationId,
'consumes': instance.consumes,
'produces': instance.produces,
'responses': instance.responses,
'parameters': instance.parameters,
'requestBody': instance.requestBody,
};
RequestBody _$RequestBodyFromJson(Map<String, dynamic> json) {
return RequestBody(
content: _contentFromJson(json['content'] as Map<String, dynamic>?),
ref: json['\$ref'] as String? ?? '',
);
}
Map<String, dynamic> _$RequestBodyToJson(RequestBody instance) =>
<String, dynamic>{
'content': instance.content,
'\$ref': instance.ref,
};
RequestContent _$RequestContentFromJson(Map<String, dynamic> json) {
return RequestContent(
schema: json['schema'] == null
? null
: SwaggerSchema.fromJson(json['schema'] as Map<String, dynamic>),
);
}
Map<String, dynamic> _$RequestContentToJson(RequestContent instance) =>
<String, dynamic>{
'schema': instance.schema,
};

View File

@ -0,0 +1,26 @@
import 'package:json_annotation/json_annotation.dart';
part 'swagger_request_items.g2.dart';
@JsonSerializable()
class SwaggerRequestItems {
SwaggerRequestItems({
required this.type,
required this.enumValues,
required this.ref,
});
@JsonKey(name: 'type', defaultValue: '')
String type;
@JsonKey(name: 'enum', defaultValue: [])
List<String> enumValues;
@JsonKey(name: '\$ref', defaultValue: '')
String ref;
Map<String, dynamic> toJson() => _$SwaggerRequestItemsToJson(this);
factory SwaggerRequestItems.fromJson(Map<String, dynamic> json) =>
_$SwaggerRequestItemsFromJson(json);
}

View File

@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_request_items.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerRequestItems _$SwaggerRequestItemsFromJson(Map<String, dynamic> json) {
return SwaggerRequestItems(
type: json['type'] as String? ?? '',
enumValues:
(json['enum'] as List<dynamic>?)?.map((e) => e as String).toList() ??
[],
ref: json[r'$ref'] as String? ?? '',
);
}
Map<String, dynamic> _$SwaggerRequestItemsToJson(
SwaggerRequestItems instance) =>
<String, dynamic>{
'type': instance.type,
'enum': instance.enumValues,
r'$ref': instance.ref,
};

View File

@ -0,0 +1,60 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/requests/parameter_item.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request_items.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
part 'swagger_request_parameter.g2.dart';
@JsonSerializable()
class SwaggerRequestParameter {
SwaggerRequestParameter(
{this.inParameter = '',
this.name = '',
this.description = '',
this.isRequired = false,
this.type = '',
this.item,
this.collectionFormat = '',
this.items,
this.schema,
this.ref = '',
this.key = ''});
@JsonKey(name: 'in', defaultValue: '')
String inParameter;
@JsonKey(name: 'name', defaultValue: '')
String name;
@JsonKey(name: 'description', defaultValue: '')
String description;
@JsonKey(name: 'required', defaultValue: false)
bool isRequired;
@JsonKey(name: '\$ref', defaultValue: '')
String ref;
@JsonKey(name: 'type', defaultValue: '')
String type;
@JsonKey(name: 'item')
ParameterItem? item;
@JsonKey(name: 'collectionFormat', defaultValue: '')
String collectionFormat;
@JsonKey(name: 'schema')
SwaggerSchema? schema;
@JsonKey(name: 'items')
SwaggerRequestItems? items;
@JsonKey(ignore: true, defaultValue: '')
String key;
Map<String, dynamic> toJson() => _$SwaggerRequestParameterToJson(this);
factory SwaggerRequestParameter.fromJson(Map<String, dynamic> json) =>
_$SwaggerRequestParameterFromJson(json);
}

View File

@ -0,0 +1,44 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_request_parameter.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerRequestParameter _$SwaggerRequestParameterFromJson(
Map<String, dynamic> json) {
return SwaggerRequestParameter(
inParameter: json['in'] as String? ?? '',
name: json['name'] as String? ?? '',
description: json['description'] as String? ?? '',
isRequired: json['required'] as bool? ?? false,
type: json['type'] as String? ?? '',
item: json['item'] == null
? null
: ParameterItem.fromJson(json['item'] as Map<String, dynamic>),
collectionFormat: json['collectionFormat'] as String? ?? '',
items: json['items'] == null
? null
: SwaggerRequestItems.fromJson(json['items'] as Map<String, dynamic>),
schema: json['schema'] == null
? null
: SwaggerSchema.fromJson(json['schema'] as Map<String, dynamic>),
ref: json[r'$ref'] as String? ?? '',
);
}
Map<String, dynamic> _$SwaggerRequestParameterToJson(
SwaggerRequestParameter instance) =>
<String, dynamic>{
'in': instance.inParameter,
'name': instance.name,
'description': instance.description,
'required': instance.isRequired,
r'$ref': instance.ref,
'type': instance.type,
'item': instance.item,
'collectionFormat': instance.collectionFormat,
'schema': instance.schema,
'items': instance.items,
};

View File

@ -0,0 +1,80 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
part 'swagger_response.g2.dart';
@JsonSerializable()
class SwaggerResponse {
SwaggerResponse({
this.description = '',
this.type = '',
this.schema,
this.enumValue = const [],
this.content,
this.ref = '',
});
@JsonKey(name: '\$ref', defaultValue: '')
String ref;
@JsonKey(name: 'description', defaultValue: '')
String description;
@JsonKey(name: 'type', defaultValue: '')
String type;
@JsonKey(name: 'schema')
SwaggerSchema? schema;
@JsonKey(name: 'enumValue', defaultValue: [])
List<String> enumValue;
@JsonKey(name: 'content', fromJson: _mapContent)
Content? content;
Map<String, dynamic> toJson() => _$SwaggerResponseToJson(this);
factory SwaggerResponse.fromJson(Map<String, dynamic> json) =>
_$SwaggerResponseFromJson(json);
}
Content? _mapContent(Map<String, dynamic>? json) {
if (json == null || json.isEmpty) {
return null;
}
final inner = json.values.first as Map<String, dynamic>;
return Content.fromJson(inner);
}
@JsonSerializable()
class Content {
Content({
this.items,
this.ref = '',
this.responseType = '',
this.type = '',
this.schema,
});
@JsonKey(name: 'responseType', defaultValue: '')
final String responseType;
@JsonKey(name: 'type', defaultValue: '')
final String type;
@JsonKey(name: 'items')
final SwaggerSchema? items;
@JsonKey(name: 'schema')
final SwaggerSchema? schema;
@JsonKey(name: 'ref', defaultValue: '')
final String ref;
Map<String, dynamic> toJson() => _$ContentToJson(this);
factory Content.fromJson(Map<String, dynamic> json) =>
_$ContentFromJson(json);
}

View File

@ -0,0 +1,55 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerResponse _$SwaggerResponseFromJson(Map<String, dynamic> json) {
return SwaggerResponse(
description: json['description'] as String? ?? '',
type: json['type'] as String? ?? '',
schema: json['schema'] == null
? null
: SwaggerSchema.fromJson(json['schema'] as Map<String, dynamic>),
enumValue: (json['enumValue'] as List<dynamic>?)
?.map((e) => e as String)
.toList() ??
[],
content: _mapContent(json['content'] as Map<String, dynamic>?),
ref: json['\$ref'] as String? ?? '',
);
}
Map<String, dynamic> _$SwaggerResponseToJson(SwaggerResponse instance) =>
<String, dynamic>{
'\$ref': instance.ref,
'description': instance.description,
'type': instance.type,
'schema': instance.schema,
'enumValue': instance.enumValue,
'content': instance.content,
};
Content _$ContentFromJson(Map<String, dynamic> json) {
return Content(
items: json['items'] == null
? null
: SwaggerSchema.fromJson(json['items'] as Map<String, dynamic>),
ref: json['\$ref'] as String? ?? '',
responseType: json['responseType'] as String? ?? '',
type: json['type'] as String? ?? '',
schema: json['schema'] == null
? null
: SwaggerSchema.fromJson(json['schema'] as Map<String, dynamic>),
);
}
Map<String, dynamic> _$ContentToJson(Content instance) => <String, dynamic>{
'responseType': instance.responseType,
'type': instance.type,
'items': instance.items,
'schema': instance.schema,
'\$ref': instance.ref,
};

View File

@ -0,0 +1,61 @@
import 'package:json_annotation/json_annotation.dart';
part 'swagger_schema.g2.dart';
@JsonSerializable()
class SwaggerSchema {
SwaggerSchema({
required this.type,
required this.originalRef,
required this.enumValuesObj,
required this.properties,
required this.items,
required this.ref,
required this.defaultValue,
required this.format,
required this.schema,
required this.oneOf,
required this.anyOf,
});
@JsonKey(name: 'type', defaultValue: '')
String type;
@JsonKey(name: 'format', defaultValue: '')
String format;
@JsonKey(name: 'default', defaultValue: null)
Object? defaultValue;
@JsonKey(name: 'originalRef', defaultValue: '')
String originalRef;
@JsonKey(name: '\$ref', defaultValue: '')
String ref;
@JsonKey(name: 'enum', defaultValue: [])
List<Object?> enumValuesObj;
List<String> get enumValues =>
enumValuesObj.map((e) => e.toString()).toList();
@JsonKey(name: 'items')
SwaggerSchema? items;
@JsonKey(name: 'properties', defaultValue: {})
Map<String, SwaggerSchema> properties;
@JsonKey(name: 'schema')
SwaggerSchema? schema;
@JsonKey(name: 'oneOf', defaultValue: [])
List<SwaggerSchema> oneOf;
@JsonKey(name: 'anyOf', defaultValue: [])
List<SwaggerSchema> anyOf;
factory SwaggerSchema.fromJson(Map<String, dynamic> json) =>
_$SwaggerSchemaFromJson(json);
Map<String, dynamic> toJson() => _$SwaggerSchemaToJson(this);
}

View File

@ -0,0 +1,52 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_schema.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerSchema _$SwaggerSchemaFromJson(Map<String, dynamic> json) {
return SwaggerSchema(
type: json['type'] as String? ?? '',
originalRef: json['originalRef'] as String? ?? '',
enumValuesObj: json['enum'] as List<dynamic>? ?? [],
properties: (json['properties'] as Map<String, dynamic>?)?.map(
(k, e) =>
MapEntry(k, SwaggerSchema.fromJson(e as Map<String, dynamic>)),
) ??
{},
items: json['items'] == null
? null
: SwaggerSchema.fromJson(json['items'] as Map<String, dynamic>),
ref: json[r'$ref'] as String? ?? '',
defaultValue: json['default'],
format: json['format'] as String? ?? '',
schema: json['schema'] == null
? null
: SwaggerSchema.fromJson(json['schema'] as Map<String, dynamic>),
oneOf: (json['oneOf'] as List<dynamic>?)
?.map((e) => SwaggerSchema.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
anyOf: (json['anyOf'] as List<dynamic>?)
?.map((e) => SwaggerSchema.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
);
}
Map<String, dynamic> _$SwaggerSchemaToJson(SwaggerSchema instance) =>
<String, dynamic>{
'type': instance.type,
'format': instance.format,
'default': instance.defaultValue,
'originalRef': instance.originalRef,
r'$ref': instance.ref,
'enum': instance.enumValuesObj,
'items': instance.items,
'properties': instance.properties,
'schema': instance.schema,
'oneOf': instance.oneOf,
'anyOf': instance.anyOf,
};

View File

@ -0,0 +1,60 @@
import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request_parameter.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
part 'swagger_components.g2.dart';
@JsonSerializable()
class SwaggerComponents {
SwaggerComponents({
required this.parameters,
required this.schemas,
required this.responses,
required this.requestBodies,
});
@JsonKey(name: 'parameters', defaultValue: {})
Map<String, SwaggerRequestParameter> parameters;
@JsonKey(name: 'schemas', defaultValue: {})
Map<String, SwaggerSchema> schemas;
@JsonKey(name: 'responses', fromJson: _mapResponses)
Map<String, SwaggerSchema> responses;
@JsonKey(name: 'requestBodies', fromJson: _mapResponses)
Map<String, SwaggerSchema> requestBodies;
Map<String, dynamic> toJson() => _$SwaggerComponentsToJson(this);
factory SwaggerComponents.fromJson(Map<String, dynamic> json) =>
_$SwaggerComponentsFromJson(json);
}
Map<String, SwaggerSchema> _mapResponses(Map<String, dynamic>? json) {
var results = <String, SwaggerSchema>{};
if (json == null) {
return results;
}
json.forEach((key, value) {
final content =
(value as Map<String, dynamic>)['content'] as Map<String, dynamic>?;
Map<String, dynamic>? appJson;
if (content?.length == 1) {
appJson = content?.values.first as Map<String, dynamic>?;
} else {
appJson = content?['application/json'] as Map<String, dynamic>?;
}
if (appJson != null && appJson['schema'] != null) {
results[key] =
SwaggerSchema.fromJson(appJson['schema'] as Map<String, dynamic>);
}
});
return results;
}

View File

@ -0,0 +1,33 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_components.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerComponents _$SwaggerComponentsFromJson(Map<String, dynamic> json) {
return SwaggerComponents(
parameters: (json['parameters'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
k, SwaggerRequestParameter.fromJson(e as Map<String, dynamic>)),
) ??
{},
schemas: (json['schemas'] as Map<String, dynamic>?)?.map(
(k, e) =>
MapEntry(k, SwaggerSchema.fromJson(e as Map<String, dynamic>)),
) ??
{},
responses: _mapResponses(json['responses'] as Map<String, dynamic>?),
requestBodies:
_mapResponses(json['requestBodies'] as Map<String, dynamic>?),
);
}
Map<String, dynamic> _$SwaggerComponentsToJson(SwaggerComponents instance) =>
<String, dynamic>{
'parameters': instance.parameters,
'schemas': instance.schemas,
'responses': instance.responses,
'requestBodies': instance.requestBodies,
};

View File

@ -0,0 +1,29 @@
import 'package:json_annotation/json_annotation.dart';
part 'swagger_info.g2.dart';
@JsonSerializable()
class SwaggerInfo {
SwaggerInfo(
{this.description = '',
this.version = '',
this.title = '',
this.termsOfService = ''});
factory SwaggerInfo.fromJson(Map<String, dynamic> json) =>
_$SwaggerInfoFromJson(json);
@JsonKey(name: 'description', defaultValue: '')
String description;
@JsonKey(name: 'version', defaultValue: '')
String version;
@JsonKey(name: 'title', defaultValue: '')
String title;
@JsonKey(name: 'termsOfService', defaultValue: '')
String termsOfService;
Map<String, dynamic> toJson() => _$SwaggerInfoToJson(this);
}

View File

@ -0,0 +1,24 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_info.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerInfo _$SwaggerInfoFromJson(Map<String, dynamic> json) {
return SwaggerInfo(
description: json['description'] as String? ?? '',
version: json['version'] as String? ?? '',
title: json['title'] as String? ?? '',
termsOfService: json['termsOfService'] as String? ?? '',
);
}
Map<String, dynamic> _$SwaggerInfoToJson(SwaggerInfo instance) =>
<String, dynamic>{
'description': instance.description,
'version': instance.version,
'title': instance.title,
'termsOfService': instance.termsOfService,
};

View File

@ -0,0 +1,25 @@
import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request_parameter.dart';
import 'package:json_annotation/json_annotation.dart';
import 'requests/swagger_request.dart';
part 'swagger_path.g2.dart';
@JsonSerializable()
class SwaggerPath {
SwaggerPath({
this.requests = const {},
this.parameters = const [],
});
@JsonKey(name: 'requests', defaultValue: {})
Map<String, SwaggerRequest> requests;
@JsonKey(name: 'parameters', defaultValue: [])
List<SwaggerRequestParameter> parameters;
Map<String, dynamic> toJson() => _$SwaggerPathToJson(this);
factory SwaggerPath.fromJson(Map<String, dynamic> json) =>
_$SwaggerPathFromJson(json);
}

View File

@ -0,0 +1,28 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_path.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerPath _$SwaggerPathFromJson(Map<String, dynamic> json) {
return SwaggerPath(
requests: (json['requests'] as Map<String, dynamic>?)?.map(
(k, e) =>
MapEntry(k, SwaggerRequest.fromJson(e as Map<String, dynamic>)),
) ??
{},
parameters: (json['parameters'] as List<dynamic>?)
?.map((e) =>
SwaggerRequestParameter.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
);
}
Map<String, dynamic> _$SwaggerPathToJson(SwaggerPath instance) =>
<String, dynamic>{
'requests': instance.requests,
'parameters': instance.parameters,
};

View File

@ -0,0 +1,84 @@
import 'package:swagger_dart_code_generator/src/code_generators/constants.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/responses/swagger_schema.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/swagger_components.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/swagger_info.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/swagger_path.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/swagger_tag.dart';
import 'package:json_annotation/json_annotation.dart';
part 'swagger_root.g2.dart';
@JsonSerializable()
class SwaggerRoot {
SwaggerRoot({
required this.basePath,
required this.components,
required this.info,
required this.host,
required this.paths,
required this.tags,
required this.schemes,
required this.parameters,
required this.definitions,
});
@JsonKey(name: 'info')
SwaggerInfo? info;
@JsonKey(name: 'host', defaultValue: '')
String host;
@JsonKey(name: 'basePath', defaultValue: '')
String basePath;
@JsonKey(name: 'tags', defaultValue: [])
List<SwaggerTag> tags;
@JsonKey(name: 'schemes', defaultValue: [])
List<String> schemes;
@JsonKey(name: 'paths', fromJson: _mapPaths)
Map<String, SwaggerPath> paths;
@JsonKey(name: 'definitions', defaultValue: {})
Map<String, SwaggerSchema> definitions;
@JsonKey(name: 'parameters', defaultValue: {})
Map<String, SwaggerRequestParameter> parameters;
@JsonKey(name: 'components')
SwaggerComponents? components;
Map<String, dynamic> toJson() => _$SwaggerRootToJson(this);
factory SwaggerRoot.fromJson(Map<String, dynamic> json) => _$SwaggerRootFromJson(json);
}
Map<String, SwaggerPath> _mapPaths(Map<String, dynamic>? paths) {
if (paths == null) {
return {};
}
return paths.map((path, pathValue) {
final value = pathValue as Map<String, dynamic>;
final parameters = value['parameters'] as List<dynamic>?;
value.removeWhere((key, value) => !supportedRequestTypes.contains(key.toLowerCase()));
return MapEntry(
path,
SwaggerPath(
parameters: parameters
?.map((parameter) => SwaggerRequestParameter.fromJson(parameter as Map<String, dynamic>))
.toList() ??
[],
requests: value.map(
(key, request) => MapEntry(
key,
SwaggerRequest.fromJson(request as Map<String, dynamic>),
),
),
),
);
});
}

View File

@ -0,0 +1,52 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_root.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerRoot _$SwaggerRootFromJson(Map<String, dynamic> json) {
return SwaggerRoot(
basePath: json['basePath'] as String? ?? '',
components: json['components'] == null
? null
: SwaggerComponents.fromJson(
json['components'] as Map<String, dynamic>),
info: json['info'] == null
? null
: SwaggerInfo.fromJson(json['info'] as Map<String, dynamic>),
host: json['host'] as String? ?? '',
paths: _mapPaths(json['paths'] as Map<String, dynamic>?),
tags: (json['tags'] as List<dynamic>?)
?.map((e) => SwaggerTag.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
schemes:
(json['schemes'] as List<dynamic>?)?.map((e) => e as String).toList() ??
[],
parameters: (json['parameters'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
k, SwaggerRequestParameter.fromJson(e as Map<String, dynamic>)),
) ??
{},
definitions: (json['definitions'] as Map<String, dynamic>?)?.map(
(k, e) =>
MapEntry(k, SwaggerSchema.fromJson(e as Map<String, dynamic>)),
) ??
{},
);
}
Map<String, dynamic> _$SwaggerRootToJson(SwaggerRoot instance) =>
<String, dynamic>{
'info': instance.info,
'host': instance.host,
'basePath': instance.basePath,
'tags': instance.tags,
'schemes': instance.schemes,
'paths': instance.paths,
'definitions': instance.definitions,
'parameters': instance.parameters,
'components': instance.components,
};

View File

@ -0,0 +1,20 @@
import 'dart:core';
import 'package:json_annotation/json_annotation.dart';
part 'swagger_tag.g2.dart';
@JsonSerializable()
class SwaggerTag {
SwaggerTag({this.name = '', this.description = ''});
factory SwaggerTag.fromJson(Map<String, dynamic> json) =>
_$SwaggerTagFromJson(json);
@JsonKey(name: 'name', defaultValue: '')
String name;
@JsonKey(name: 'description', defaultValue: '')
String description;
Map<String, dynamic> toJson() => _$SwaggerTagToJson(this);
}

View File

@ -0,0 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'swagger_tag.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SwaggerTag _$SwaggerTagFromJson(Map<String, dynamic> json) {
return SwaggerTag(
name: json['name'] as String? ?? '',
description: json['description'] as String? ?? '',
);
}
Map<String, dynamic> _$SwaggerTagToJson(SwaggerTag instance) =>
<String, dynamic>{
'name': instance.name,
'description': instance.description,
};

View File

@ -0,0 +1,222 @@
import 'package:build/build.dart';
import 'package:code_builder/code_builder.dart';
import 'package:swagger_dart_code_generator/src/extensions/file_name_extensions.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:swagger_dart_code_generator/src/swagger_code_generator.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/responses/swagger_schema.dart';
import 'package:universal_io/io.dart';
import 'package:dart_style/dart_style.dart';
///Returns instance of SwaggerDartCodeGenerator
SwaggerDartCodeGenerator swaggerCodeBuilder(BuilderOptions options) => SwaggerDartCodeGenerator(options);
const _inputFileExtensions = ['.swagger', '.json'];
const String _outputFileExtension = '.dart';
const String _outputEnumsFileExtension = '_enums.dart';
const String _outputModelsFileExtension = '_models.dart';
const String _indexFileName = 'client_index.dart';
// const String _mappingFileName = 'client_mapping.dart';
Map<String, List<String>> _generateExtensions(GeneratorOptions options) {
final filesList = Directory(options.inputFolder)
.listSync()
.where((FileSystemEntity file) => _inputFileExtensions.any((ending) => file.path.endsWith(ending)));
final result = <String, List<String>>{};
filesList.forEach((FileSystemEntity element) {
final name = getFileNameBase(element.path);
result[element.path] = <String>[
'${options.outputFolder}$name$_outputFileExtension',
'${options.outputFolder}$name$_outputEnumsFileExtension',
'${options.outputFolder}$name$_outputModelsFileExtension',
];
});
///Register additional outputs in first input
result[filesList.first.path]!.add('${options.outputFolder}$_indexFileName');
// result[filesList.first.path]!.add('${options.outputFolder}$_mappingFileName');
return result;
}
///Root library entry
class SwaggerDartCodeGenerator implements Builder {
SwaggerDartCodeGenerator(BuilderOptions builderOptions) {
options = GeneratorOptions.fromJson(builderOptions.config);
}
@override
Map<String, List<String>> get buildExtensions => _buildExtensionsCopy ??= _generateExtensions(options);
Map<String, List<String>>? _buildExtensionsCopy;
late GeneratorOptions options;
final DartFormatter _formatter = DartFormatter();
@override
Future<void> build(BuildStep buildStep) async {
final fileNameWithExtension = buildStep.inputId.pathSegments.last.replaceAll('-', '_');
final fileNameWithoutExtension = getFileNameBase(fileNameWithExtension);
final contents = await buildStep.readAsString(buildStep.inputId);
final codeGenerator = SwaggerCodeGenerator();
final responses =
codeGenerator.generateResponses(contents, getFileNameWithoutExtension(fileNameWithExtension), options);
final requestBodies =
codeGenerator.generateRequestBodies(contents, getFileNameWithoutExtension(fileNameWithExtension), options);
final enums = codeGenerator.generateEnums(contents, getFileNameWithoutExtension(fileNameWithExtension));
final converter =
codeGenerator.generateConverter(contents, getFileNameWithoutExtension(fileNameWithExtension), options);
var requestClass = <String, dynamic>{};
final requests = codeGenerator.generateRequests(contents, getClassNameFromFileName(fileNameWithExtension),
getFileNameWithoutExtension(fileNameWithExtension), options, requestClass);
// print('---------');
// print(requestClass);
final models = codeGenerator.generateModels(
contents, getFileNameWithoutExtension(fileNameWithExtension), options, requestClass);
final imports = codeGenerator.generateImportsContent(contents, fileNameWithoutExtension, models.isNotEmpty,
options.buildOnlyModels, enums.isNotEmpty, options.separateModels, options);
// final customDecoder = codeGenerator.generateCustomJsonConverter(
// contents, getFileNameWithoutExtension(fileNameWithExtension), options);
// final dateToJson = codeGenerator.generateDateToJson(contents);
final copyAssetId =
AssetId(buildStep.inputId.package, '${options.outputFolder}$fileNameWithoutExtension$_outputFileExtension');
if (!options.separateModels || !options.buildOnlyModels) {
await buildStep.writeAsString(
copyAssetId,
_generateFileContent(
imports, requests, converter, options.separateModels ? '' : models,
options.separateModels ? '' : responses, options.separateModels ? '' : requestBodies, '', '',
// customDecoder,
// dateToJson,
));
}
if (enums.isNotEmpty) {
///Write enums
final formatterEnums = _tryFormatCode(enums);
final enumsAssetId = AssetId(
buildStep.inputId.package, '${options.outputFolder}$fileNameWithoutExtension$_outputEnumsFileExtension');
await buildStep.writeAsString(enumsAssetId, formatterEnums);
}
if (options.separateModels) {
///Write models to separate file
final formattedModels = _tryFormatCode(_generateSeparateModelsFileContent(
models,
responses,
requestBodies,
fileNameWithoutExtension,
enums.isNotEmpty,
));
final enumsAssetId = AssetId(
buildStep.inputId.package, '${options.outputFolder}$fileNameWithoutExtension$_outputModelsFileExtension');
await buildStep.writeAsString(enumsAssetId, formattedModels);
}
///Write additional files on first input
// if (buildExtensions.keys.first == buildStep.inputId.path) {
// await _generateAdditionalFiles(contents, buildStep.inputId, buildStep, models.isNotEmpty);
// }
}
String _generateFileContent(String imports, String requests, String converter, String models, String responses,
String requestBodies, String customDecoder, String dateToJson) {
final result = """
$imports
${options.buildOnlyModels ? '' : requests}
${options.withConverter && !options.buildOnlyModels ? converter : ''}
$models
$responses
$requestBodies
${options.buildOnlyModels ? '' : customDecoder}
$dateToJson
""";
return _tryFormatCode(result);
}
String _tryFormatCode(String code) {
try {
final formattedResult = _formatter.format(code);
return formattedResult;
} catch (e) {
print('''[WARNING] Code formatting failed.
Please raise an issue on https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/
Reason: $e''');
return code;
}
}
// Future<void> _generateAdditionalFiles(
// String swaggerCode, AssetId inputId, BuildStep buildStep, bool hasModels) async {
// final codeGenerator = SwaggerCodeGenerator();
// final indexAssetId = AssetId(inputId.package, '${options.outputFolder}$_indexFileName');
// final imports = codeGenerator.generateIndexes(swaggerCode, buildExtensions);
// if (!options.buildOnlyModels) {
// await buildStep.writeAsString(indexAssetId, _formatter.format(imports));
// }
// if (options.withConverter && !options.buildOnlyModels) {
// final mappingAssetId = AssetId(inputId.package, '${options.outputFolder}$_mappingFileName');
// final mapping = codeGenerator.generateConverterMappings(swaggerCode, buildExtensions, hasModels);
// await buildStep.writeAsString(mappingAssetId, _formatter.format(mapping));
// }
// }
String _generateSeparateModelsFileContent(
String models,
String responses,
String requestBodies,
String fileNameWithoutExtension,
bool hasEnums,
) {
final enumsImport = hasEnums ? "import '${fileNameWithoutExtension}_enums.dart' as enums;" : '';
return '''
import 'package:json_annotation/json_annotation.dart';
import 'package:collection/collection.dart';
$enumsImport
part '${fileNameWithoutExtension}_models.g.dart';
$models
$responses
$requestBodies
''';
}
}

View File

@ -0,0 +1,33 @@
name: swagger_dart_code_generator
version: 2.2.3
homepage: https://github.com/epam-cross-platform-lab/swagger-dart-code-generator
repository: https://github.com/epam-cross-platform-lab/swagger-dart-code-generator
issue_tracker: https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues
description: Have you been turned into a problem with writing code for Http
requests? This package can help. It has all of the Http and model codegen
functionality you have been looking for.
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
build: ^2.0.2
path: ^1.8.0
# markdown: ^4.0.0
recase: ^4.0.0
json_annotation: ^4.1.0
universal_io: ^2.0.4
collection: ^1.15.0
dart_style: ^2.2.1
code_builder: ^4.0.0
dev_dependencies:
build_runner: ^2.1.2
json_serializable: ^5.0.0
remove_from_coverage: ^2.0.0
pedantic: ^1.11.0
test: ^1.17.5

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
const String model_with_parameters = '''
{
"components": {
"schemas": {
"ActiveOrderAndListSummary": {
"type": "object",
"properties": {
"closingTime": {
"type": "string",
"format": "date-time"
},
"orderLastChangedTime": {
"type": "string",
"format": "date-time"
},
"orderedProducts": {
"type": "array",
"items": {
"originalRef": "OrderedProductCard",
"\$ref": "#/definitions/OrderedProductCard"
}
}
},
"title": "ActiveOrderAndListSummary"
}
},
"responses": {
"SpaResponse": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"required": [
"showPageAvailable"
],
"properties": {
"id": {
"type": "string",
"description": "Crid show (VOD)"
},
"showPageAvailable": {
"type": "boolean",
"description": "Flag indicating showPage availability"
}
}
}
}
}
}
}
}
}
''';
const String model_with_parameters_v2 = '''
{
"definitions": {
"ActiveOrderAndListSummary": {
"type": "object",
"properties": {
"closingTime": {
"type": "string",
"format": "date-time"
},
"orderLastChangedTime": {
"type": "string",
"format": "date-time"
},
"orderedProducts": {
"type": "array",
"items": {
"originalRef": "OrderedProductCard",
"\$ref": "#/definitions/OrderedProductCard"
}
}
},
"title": "ActiveOrderAndListSummary"
}
}
}
''';
const String model_with_enunm_array_parameters_v2 = '''
{
"definitions": {
"ActiveOrderAndListSummary": {
"type": "array",
"items" : {
"type" : "enum",
"items" :[ "one" ]
}
}
}
}
''';

View File

@ -0,0 +1,13 @@
import 'package:test/test.dart';
import 'package:swagger_dart_code_generator/src/extensions/file_name_extensions.dart';
void main() {
group('Additions generator tests', () {
test('Should generate mapping for files', () {
const fileName = 'example_file.swagger.dart';
var result = getFileNameWithoutExtension(fileName);
var expandedResult = 'example_file';
expect(result, equals(expandedResult));
});
});
}

View File

@ -0,0 +1,69 @@
import 'package:swagger_dart_code_generator/src/code_generators/swagger_additions_generator.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:test/test.dart';
void main() {
group('Additions generator tests', () {
final generator = SwaggerAdditionsGenerator();
// test('Should generate mapping for files', () {
// final result = generator.generateConverterMappings(<String, List<String>>{
// 'someFile.dart': <String>['someFile.swagger.dart'],
// 'secondFile.dart': <String>['secondFile.swagger.dart']
// }, true);
// expect(result, contains('...SomeFileJsonDecoderMappings'));
// expect(result, contains('...SecondFileJsonDecoderMappings'));
// });
test('Should generate correct imports', () {
final result = generator.generateImportsContent('swagger.fileName', true, false, false, false, []);
expect(result, contains("part 'swagger.fileName.swagger.chopper.dart';"));
expect(result, contains("part 'swagger.fileName.swagger.g.dart';"));
});
test('Should generate correct imports', () {
final result = generator.generateImportsContent('swagger.fileName', true, false, true, false, []);
expect(result, contains("import 'swagger.fileName.enums.swagger.dart' as enums;"));
});
test('Should generate indexes file', () {
final result = generator.generateIndexes(<String, List<String>>{
'someFile.dart': <String>['someFile.swagger.dart'],
'secondFile.dart': <String>['secondFile.swagger.dart']
});
expect(result, contains("export 'someFile.dart.dart' show SomeFile;"));
expect(result, contains("export 'secondFile.dart.dart' show SecondFile;"));
});
});
group('Test for generateCustomJsonConverter', () {
final generator = SwaggerAdditionsGenerator();
test('Should generate custom json converter', () {
const fileName = 'example_swagger';
const expectedResult = 'CustomJsonDecoder(ExampleSwaggerJsonDecoderMappings)';
final result = generator.generateCustomJsonConverter(
fileName,
GeneratorOptions(
inputFolder: '',
outputFolder: '',
),
);
expect(result, contains(expectedResult));
});
});
group('Test for generateDateToJson', () {
final generator = SwaggerAdditionsGenerator();
test('Should dateToJson with parameter', () {
const expectedResult = 'String? _dateToJson(DateTime? date)';
final result = generator.generateDateToJson();
expect(result, contains(expectedResult));
});
});
}

View File

@ -0,0 +1,47 @@
import 'package:swagger_dart_code_generator/src/code_generators/swagger_converter_generator.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:test/test.dart';
import '../converter_generator_definitions.dart';
void main() {
group('Converter generator tests', () {
final generator = SwaggerConverterGenerator();
const fileName = 'file_name';
test('Should create fromJsonFactory for model', () {
final result = generator.generate(
model_with_parameters,
fileName,
GeneratorOptions(inputFolder: '', outputFolder: ''),
);
expect(
result,
contains(
'ActiveOrderAndListSummary: ActiveOrderAndListSummary.fromJsonFactory'));
});
test(
'Should not create fromJsonFactory for model with array enums parameters',
() {
final result = generator.generate(model_with_enunm_array_parameters_v2,
fileName, GeneratorOptions(inputFolder: '', outputFolder: ''));
final isContains = result.contains(
'ActiveOrderAndListSummary: ActiveOrderAndListSummary.fromJsonFactory');
expect(isContains, equals(false));
});
test('Should create fromJsonFactory for model', () {
final result = generator.generate(model_with_parameters_v2, fileName,
GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(
result,
contains(
'ActiveOrderAndListSummary: ActiveOrderAndListSummary.fromJsonFactory'));
});
});
}

View File

@ -0,0 +1,150 @@
import 'package:swagger_dart_code_generator/src/code_generators/swagger_enums_generator.dart';
//import 'package:swagger_dart_code_generator/src/code_generators/v2/swagger_enums_generator_v2.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v3/swagger_enums_generator_v3.dart';
import 'package:swagger_dart_code_generator/src/swagger_models/requests/swagger_request_parameter.dart';
import 'package:test/test.dart';
import '../code_examples.dart';
void main() {
final generator = SwaggerEnumsGeneratorV3();
//final generatorv2 = SwaggerEnumsGeneratorV2();
group('Generate', () {
// test('Should generate enum from models', () {
// final result = generator.generate(model_with_parameters_v3, 'test_file');
// expect(result, contains('enum SomeEnumModel'));
// });
// test('Should generate enum from models', () {
// final result =
// generatorv2.generate(model_with_parameters_v2, 'test_file');
// expect(result, contains('enum ActiveOrderAndListSummaryEnumValue'));
// });
test('Should generate enum from request parameter', () {
final result =
generator.generate(request_with_enum_in_parameter, 'test_file');
expect(result, contains('enum V3OrderOrderIdStatePutOrderStateRequest'));
});
// test('Should generate enums from responses', () {
// final result =
// generator.generate(schemas_with_enums_in_properties, 'test_file');
// expect(result, contains('enum SpaResponse'));
// });
});
group('Converter generator tests', () {
test('Should generate enum values', () {
final values = <String>['file_sup'];
const output = "\t@JsonValue('file_sup')\n\tfileSup";
final result = generator.getEnumValuesContent(values);
expect(result, contains(output));
});
test('Should return enum field name', () {
const name = 'cat-dog_ Cars';
const output = 'catDogCars';
final result = SwaggerEnumsGenerator.getValidatedEnumFieldName(name);
expect(result, contains(output));
});
test('Should return \$null if name is null', () {
const name = 'null';
const output = '\$null';
final result = SwaggerEnumsGenerator.getValidatedEnumFieldName(name);
expect(result, contains(output));
});
});
group('Tests for getValidatedEnumFieldName', () {
test('Should remove numbers at beginning if it is key word', () {
final result = SwaggerEnumsGenerator.getValidatedEnumFieldName('007');
expect(result, equals('value_007'));
});
test('Should remove numbers at beginning if it is key word', () {
final result =
SwaggerEnumsGenerator.getEnumNamesFromRequests(request_with_enum);
expect(result[0], equals('PetsPetIdItemsGetContentType'));
});
test('Should remove numbers at beginning if it is key word', () {
final result = SwaggerEnumsGenerator.getEnumNamesFromRequests(
request_with_list_of_enum_in_parameter);
expect(result[0], equals('V3OrderOrderIdStatePutOrderStateRequest'));
});
});
group('generateEnumContentIfPossible', () {
final generator = SwaggerEnumsGeneratorV3();
test('Should generate enum', () {
final map = <String, dynamic>{
'items': {
'enum': ['Item1', 'Item2']
}
};
const enumName = 'TestName';
final result = generator.generateEnumContentIfPossible(map, enumName);
expect(result, contains('enum TestName'));
});
});
group('generateEnumName', () {
final generator = SwaggerEnumsGeneratorV3();
test('Should generate enum name', () {
const className = 'animal';
const enumName = 'cat';
const expectedResult = 'AnimalCat';
final result = generator.generateEnumName(className, enumName);
expect(result, contains(expectedResult));
});
});
group('generateEnumValuesContent', () {
final generator = SwaggerEnumsGeneratorV3();
test('Should return enum values', () {
final list = <String>['Cats', 'dogs', 'Forgs'];
const expectedResult = "\t@JsonValue('Cats')\n cats";
final result = generator.generateEnumValuesContent(list);
expect(result, contains(expectedResult));
});
});
group('getOriginalOrOverriddenRequestParameter', () {
test('Should override parameter if needed', () {
final incoming =
SwaggerRequestParameter(ref: '#definitions/TestParameter');
final overriddenParameters = [
SwaggerRequestParameter(
name: 'TestParameter', type: 'Overridden parameter')
];
final result =
SwaggerEnumsGenerator.getOriginalOrOverriddenRequestParameter(
incoming, overriddenParameters);
expect(result.type, equals('Overridden parameter'));
});
test('Should NOT override parameter if needed', () {
final incoming = SwaggerRequestParameter(
ref: '#definitions/TestParameterWrong', name: 'Original parameter');
final overriddenParameters = [
SwaggerRequestParameter(
key: 'TestParameter', name: 'Overridden parameter')
];
final result =
SwaggerEnumsGenerator.getOriginalOrOverriddenRequestParameter(
incoming, overriddenParameters);
expect(result.name, equals('Original parameter'));
});
});
}

View File

@ -0,0 +1,704 @@
import 'package:swagger_dart_code_generator/src/code_generators/swagger_models_generator.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v2/swagger_models_generator_v2.dart';
import 'package:swagger_dart_code_generator/src/code_generators/v3/swagger_models_generator_v3.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:test/test.dart';
import '../code_examples.dart';
void main() {
final generator = SwaggerModelsGeneratorV3();
final generator2 = SwaggerModelsGeneratorV2();
group('generate', () {
const fileName = 'order_service.dart';
// test('Should parse object name as a field Type', () {
// final result = generator.generate(model_with_parameters_v3, fileName,
// GeneratorOptions(inputFolder: '', outputFolder: '', ) );
// expect(
// result, contains('final enums.TokensResponseTokenType? tokenType'));
// });
// test('Should generate .toLower() when caseSensitive: false', () {
// final result = generator.generate(
// model_with_parameters_v3,
// fileName,
// GeneratorOptions(
// enumsCaseSensitive: false, inputFolder: '', outputFolder: ''));
// expect(
// result,
// contains(
// 'element.value.toLowerCase() == someEnumModel.toLowerCase()'));
// });
// test('Should NOT generate .toLower() when caseSensitive: false', () {
// final result = generator.generate(
// model_with_parameters_v3,
// fileName,
// GeneratorOptions(
// enumsCaseSensitive: true, inputFolder: '', outputFolder: ''));
// expect(result, contains('element.value == someEnumModel'));
// });
// test('Should parse object name as a field Type', () {
// final result = generator2.generate(model_with_parameters_v2, fileName,
// GeneratorOptions(inputFolder: '', outputFolder: '', {}));
// expect(
// result,
// contains(
// 'final enums.ActiveOrderAndListSummaryShoppingType? shoppingType'));
// });
// test('Should parse object name as a field Type', () {
// const expectedResult = "@JsonKey(name: 'expires_in', defaultValue: 19)";
// final generatorOptions = GeneratorOptions(
// defaultValuesMap: <DefaultValueMap>[
// DefaultValueMap(
// typeName: 'int',
// defaultValue: '19',
// )
// ],
// inputFolder: '',
// outputFolder: '',
// );
// final result = generator.generate(
// model_with_parameters_v3, fileName, generatorOptions);
// expect(result, contains(expectedResult));
// });
});
group('generateDefaultValueFromMap', () {
test('Should return default value', () {
const defaultValue = 'true';
const typeName = 'bool';
const expectedResult = 'true';
final result =
generator.generateDefaultValueFromMap(DefaultValueMap(defaultValue: defaultValue, typeName: typeName));
expect(result, contains(expectedResult));
});
test('Should return default from switch', () {
const defaultValue = 'Animal';
const typeName = 'Object';
const expectedResult = 'Animal';
final result =
generator.generateDefaultValueFromMap(DefaultValueMap(defaultValue: defaultValue, typeName: typeName));
expect(result, contains(expectedResult));
});
});
group('getParameterTypeName', () {
test('Should return validate parameter type name', () {
const className = 'Animal';
const parameterName = 'orderId';
const parameter = <String, dynamic>{'type': 'object'};
const expectedResult = 'Object';
final result = generator.getParameterTypeName(className, parameterName, parameter, '', null);
expect(result, contains(expectedResult));
});
test('Should return Object, because we dont jave map[items]', () {
const className = 'Animal';
const parameterName = 'orderId';
const parameter = <String, dynamic>{'type': 'array'};
const expectedResult = 'Object';
final result = generator.getParameterTypeName(className, parameterName, parameter, '', null);
expect(result, contains(expectedResult));
});
test('Should return Object, because we have map[oneOf]', () {
const className = 'Animal';
const parameterName = 'orderId';
const parameter = <String, dynamic>{'oneOf': 'animals'};
const expectedResult = 'Object';
final result = generator.getParameterTypeName(className, parameterName, parameter, '', null);
expect(result, contains(expectedResult));
});
test('Should return Object', () {
const className = 'Animal';
const parameterName = 'orderId';
const expectedResult = 'Object';
final result = generator.getParameterTypeName(className, parameterName, {}, '', null);
expect(result, contains(expectedResult));
});
test('Should return validate parameter type name', () {
const className = 'Animal';
const parameterName = 'orderId';
const parameter = <String, dynamic>{'\$ref': '#/definitions/Pet'};
const expectedResult = 'Pet';
final result = generator.getParameterTypeName(className, parameterName, parameter, '', null);
expect(result, contains(expectedResult));
});
test('Should return optional name parameter', () {
const className = 'Animal';
const parameterName = 'orderId';
const refNameParameter = 'animals_Object';
const expectedResult = 'AnimalsObject';
final result = generator.getParameterTypeName(className, parameterName, {}, '', refNameParameter);
expect(result, contains(expectedResult));
});
test('Should return DateTime', () {
const className = 'Animal';
const parameterName = 'orderId';
const parameter = <String, dynamic>{'type': 'string', 'format': 'date-time'};
const expectedResult = 'DateTime';
final result = generator.getParameterTypeName(className, parameterName, parameter, '', null);
expect(result, contains(expectedResult));
});
});
group('generateFieldName', () {
test('Should return validate field name', () {
const name = 'Cat_Dog-Animals';
const expectedResult = 'catDogAnimals';
final result = SwaggerModelsGenerator.generateFieldName(name);
expect(result, contains(expectedResult));
});
test('Should return \$forbiddenFieldName', () {
const name = '#';
const expectedResult = '\$forbiddenFieldName';
final result = SwaggerModelsGenerator.generateFieldName(name);
expect(result, contains(expectedResult));
});
test('Should return \$null', () {
const name = 'null';
const expectedResult = '\$null';
final result = SwaggerModelsGenerator.generateFieldName(name);
expect(result, contains(expectedResult));
});
test('Should return \$number', () {
const name = '5element';
const expectedResult = '\$5element';
final result = SwaggerModelsGenerator.generateFieldName(name);
expect(result, contains(expectedResult));
});
});
group('generatePropertyContentByDefault', () {
test('Should return property with JsonKey', () {
final propertyEntryMap = <String, dynamic>{'originalRef': 'Pet'};
const propertyName = 'shipDate';
const jsonKeyExpendedResult = "@JsonKey(name: '$propertyName'";
final result = generator.generatePropertyContentByDefault(
propertyEntryMap, propertyName, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpendedResult));
});
test('Should generate includeIfNull if option is true', () {
final propertyEntryMap = <String, dynamic>{'originalRef': 'Pet'};
const propertyName = 'shipDate';
final result = generator.generatePropertyContentByDefault(propertyEntryMap, propertyName, [], [],
GeneratorOptions(includeIfNull: false, inputFolder: '', outputFolder: ''));
expect(result, contains(', includeIfNull: false'));
});
test('Should NOT generate includeIfNull if option is false', () {
final propertyEntryMap = <String, dynamic>{'originalRef': 'Pet'};
const propertyName = 'shipDate';
final result = generator.generatePropertyContentByDefault(propertyEntryMap, propertyName, [], [],
GeneratorOptions(includeIfNull: null, inputFolder: '', outputFolder: ''));
expect(result.contains(', includeIfNull: false'), equals(false));
});
});
group('generatePropertyContentByRef', () {
test('Should return property with JsonKey', () {
final propertyEntryMap = <String, dynamic>{'\$ref': '#/definitions/Pet'};
const propertyName = 'shipDate';
const propertyKey = 'shipDateGet';
const className = 'Animals';
const jsonKeyExpendedResult = "@JsonKey(name: '$propertyKey'";
const expectedResult = '\t$jsonKeyExpendedResult)\n\tfinal Pet? $propertyName;';
final result = generator.generatePropertyContentByRef(
propertyEntryMap,
propertyName,
propertyKey,
className,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains(jsonKeyExpendedResult));
expect(result, contains(expectedResult));
});
test('Should add toJsonFromJson', () {
final propertyEntryMap = <String, dynamic>{'\$ref': '#/definitions/Pet'};
const propertyName = 'shipDate';
const propertyKey = 'shipDateGet';
const className = 'Animals';
final result = generator.generatePropertyContentByRef(
propertyEntryMap,
propertyName,
propertyKey,
className,
['enums.Pet'],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('toJson: petToJson, fromJson: petFromJson'));
});
});
group('generateEnumPropertyContent', () {
test('Should return enum property with JsonKey with fromJson and toJson', () {
const key = 'dog';
const className = 'animals';
const jsonKeyExpectedResult = 'toJson: animalsDogToJson, fromJson: animalsDogFromJson';
const expectedResult = 'final AnimalsDog? dog;';
final result = generator.generateEnumPropertyContent(
key, className, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(expectedResult));
});
});
group('generateModelClassContent', () {
test('Should return model class content', () {
const map = <String, dynamic>{};
const className = 'Animals';
const useDefaultNullForLists = false;
const classExpectedResult = 'class Animals {';
const factoryConstructorExpectedResult =
'\tfactory Animals.fromJson(Map<String, dynamic> json) => _\$AnimalsFromJson(json);\n';
final result = generator.generateModelClassContent(className, map, {}, <DefaultValueMap>[],
useDefaultNullForLists, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(classExpectedResult));
expect(result, contains(factoryConstructorExpectedResult));
});
test('Should return model class content', () {
const map = <String, dynamic>{};
const className = 'Animals';
const useDefaultNullForLists = false;
const classExpectedResult = 'class Animals {';
const factoryConstructorExpectedResult =
'\tfactory Animals.fromJson(Map<String, dynamic> json) => _\$AnimalsFromJson(json);\n';
final result = generator2.generateModelClassContent(className, map, {}, <DefaultValueMap>[],
useDefaultNullForLists, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(classExpectedResult));
expect(result, contains(factoryConstructorExpectedResult));
});
});
group('generateConstructorPropertiesContent', () {
test('Should return empty', () {
const expectedResult = '';
final result = generator.generateConstructorPropertiesContent(
'',
{},
GeneratorOptions(inputFolder: '', outputFolder: ''),
[],
[],
[],
);
expect(result, contains(expectedResult));
});
test('Should return validate constructor property', () {
final map = <String, dynamic>{
'Animal': {'type': 'dog'}
};
const expectedResult = 'this.animal';
final result = generator.generateConstructorPropertiesContent(
'',
map,
GeneratorOptions(inputFolder: '', outputFolder: ''),
[],
[],
[],
);
expect(result, contains(expectedResult));
});
});
group('generatePropertyContentBySchema', () {
test('Should return property content by schema', () {
final map = <String, dynamic>{
'schema': <String, dynamic>{'\$ref': '#/definitions/Pet'}
};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
const jsonKeyExpectedResult = "\t@JsonKey(name: 'Dog')\n";
const fieldExpectedResult = '\tfinal Pet? dog';
final result = generator.generatePropertyContentBySchema(
map,
propertyName,
propertyKey,
className,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(fieldExpectedResult));
});
test('Should add fromJson and toJson by ref', () {
final map = <String, dynamic>{
'schema': <String, dynamic>{'\$ref': '#/definitions/Pet'}
};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generatePropertyContentBySchema(
map,
propertyName,
propertyKey,
className,
['enums.Pet'],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('toJson: petToJson, fromJson: petFromJson'));
});
});
group('generatePropertiesContent', () {
test('Should return properties from ref', () {
final map = <String, dynamic>{
'Animals': <String, dynamic>{'\$ref': '#/definitions/Pet'}
};
const className = 'Animals';
const jsonKeyExpectedResult = "\t@JsonKey(name: 'Animals')\n";
const fieldExpectedResult = 'final Pet? animals';
final result = generator.generatePropertiesContent(
map, {}, className, <DefaultValueMap>[], false, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(fieldExpectedResult));
});
test('Should return properties from schema', () {
final map = <String, dynamic>{
'Animals': <String, dynamic>{
'schema': <String, dynamic>{'\$ref': '#/definitions/Pet'}
}
};
const className = 'Animals';
const jsonKeyExpectedResult = "\t@JsonKey(name: 'Animals')\n";
const fieldExpectedResult = 'final Pet? animals';
final result = generator.generatePropertiesContent(
map, {}, className, <DefaultValueMap>[], false, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(fieldExpectedResult));
});
test('Should return properties from default originalRef', () {
final map = <String, dynamic>{
'Animals': <String, dynamic>{'originalRef': 'Pet'}
};
const className = 'Animals';
const jsonKeyExpectedResult = "\t@JsonKey(name: 'animals')\n";
const fieldExpectedResult = 'final Pet? animals';
final result = generator.generatePropertiesContent(
map, {}, className, <DefaultValueMap>[], false, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(fieldExpectedResult));
});
test('Should return property \$with', () {
final map = <String, dynamic>{
'with': <String, dynamic>{'originalRef': 'Pet'}
};
const className = 'Animals';
const jsonKeyExpectedResult = "\t@JsonKey(name: '\$with')\n";
const fieldExpectedResult = 'final Pet? \$with';
final result = generator.generatePropertiesContent(
map, {}, className, <DefaultValueMap>[], false, [], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(fieldExpectedResult));
});
});
group('generateListPropertyContent', () {
test('Should return List<Object>', () {
final map = <String, dynamic>{'items': null};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
const jsonKeyExpectedResult = "@JsonKey(name: 'Dog', defaultValue: <Object>[])";
const propertyExpectedResult = 'final List<Object>? dog';
final result = generator.generateListPropertyContent(
propertyName,
propertyKey,
className,
map,
false,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains(jsonKeyExpectedResult));
expect(result, contains(propertyExpectedResult));
});
test('Should add fromJson and toJson', () {
final map = <String, dynamic>{
'items': {'originalRef': 'Dog'}
};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generateListPropertyContent(
propertyName,
propertyKey,
className,
map,
false,
['Dog'],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('toJson: dogListToJson, fromJson: dogListFromJson'));
});
test('Should return List<Object>', () {
final map = <String, dynamic>{
'items': {'originalRef': 'TestOriginalRef'}
};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generateListPropertyContent(
propertyName,
propertyKey,
className,
map,
false,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('final List<TestOriginalRef>? dog;'));
});
test('Should return List<Object> by ref', () {
final map = <String, dynamic>{
'items': {'\$ref': '#/definitions/TestObject'}
};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generateListPropertyContent(
propertyName,
propertyKey,
className,
map,
false,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('final List<TestObject>? dog;'));
});
});
group('generatePropertyContentByType', () {
test('Should return property content by schema', () {
final map = <String, String>{'type': 'enum'};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generatePropertyContentByType(
map,
propertyName,
propertyKey,
className,
<DefaultValueMap>[],
false,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('toJson: animalsDogToJson, fromJson: animalsDogFromJson'));
});
test('Should return property content by schema', () {
final map = <String, String>{'type': 'array'};
const propertyName = 'dog';
const className = 'Animals';
const propertyKey = 'Dog';
final result = generator.generatePropertyContentByType(
map,
propertyName,
propertyKey,
className,
<DefaultValueMap>[],
false,
[],
[],
GeneratorOptions(inputFolder: '', outputFolder: ''),
{},
);
expect(result, contains('final List<Object>? dog;'));
});
});
group('getModelInheritedProperties', () {
// test('Should generate 2 levels of inheritance', () {
// final result =
// generator.generate(model_with_inheritance, 'MyClass', GeneratorOptions(inputFolder: '', outputFolder: ''));
// expect(result, contains('class ExtendedErrorModel extends BasicErrorModel'));
// });
// test('Should generate 3 levels of inheritance', () {
// final result = generator.generate(
// model_with_inheritance_3_levels, 'MyClass', GeneratorOptions(inputFolder: '', outputFolder: ''));
// expect(result, contains('class MostExtendedErrorModel extends ExtendedErrorModel'));
// expect(result, contains('class ExtendedErrorModel extends BasicErrorModel'));
// });
});
group('Tests for getValidatedClassName', () {
test('Should', () {
final result = SwaggerModelsGenerator.getValidatedClassName('Request');
expect(result, equals('Request\$'));
});
});
group('Tests for generateGeneralPropertyContent', () {
test('Should', () {
final result = generator.generateGeneralPropertyContent('name', 'key', 'className', [],
{'\$ref': 'ClassNameName'}, ['enums.ClassNameName'], [], GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains('final enums.ClassNameName? name;'));
});
});
group('Tests for generateResponses', () {
test('Should generate empty string for V2', () {
final result = generator2.generateResponses(
schemas_responses_with_response, 'fileName', GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, equals(''));
});
test('Should generate class from responses V3', () {
final result = generator.generateResponses(
schemas_responses_with_response, 'fileName', GeneratorOptions(inputFolder: '', outputFolder: ''));
expect(result, contains('class SpaResponse'));
});
test('Should generate class from responses V3 and Schemas', () {
final result = generator.generateResponses(
schemas_responses_with_response_and_schemas,
'fileName',
GeneratorOptions(
inputFolder: '',
outputFolder: '',
));
expect(result, contains('class SpaResponse'));
});
});
group('Tests for getAllEnumNames', () {
test('Should', () {
final result = generator2.getAllEnumNames(enum_as_definition_v2);
expect(result, contains('enums.SpaResponse'));
});
test('Should get enum name from schemas', () {
final result = generator.getAllEnumNames(schemas_with_enums_in_properties);
expect(result, contains('enums.SpaSchemaSuccessValues'));
});
test('Should get enum name from responses', () {
final result = generator.getAllEnumNames(schemas_with_enums_in_properties);
expect(result, contains('enums.SpaResponse'));
});
test('Should get enum name from responses with Enum items', () {
final result = generator.getAllEnumNames(schemas_with_enums_in_properties);
expect(result, contains('enums.SpaEnumResponseFailedValued'));
});
});
group('Tests for models from responses', () {
// test('Should generate correct model from response', () {
// final result = generator.generate(
// request_with_return_type_injected,
// 'my_service',
// GeneratorOptions(
// inputFolder: '',
// outputFolder: '',
// ));
// expect(result, contains('class ModelItemsGet\$Response'));
// });
});
}

View File

@ -0,0 +1,57 @@
import 'package:swagger_dart_code_generator/src/code_generators/swagger_requests_generator.dart';
import 'package:swagger_dart_code_generator/src/models/generator_options.dart';
import 'package:test/test.dart';
import 'test_data.dart';
void main() {
group('Additions generator tests', () {
final generator = SwaggerRequestsGenerator();
// test('Should generate CarsApi', () {
// final result = generator.generate(
// code: carsService,
// className: 'CarsService',
// fileName: 'cars_service',
// options: GeneratorOptions(
// inputFolder: '',
// outputFolder: '',
// ignoreHeaders: true,
// responseOverrideValueMap: [
// ResponseOverrideValueMap(
// method: 'get',
// url: '/cars/schemaRefBody',
// overriddenValue: 'String',
// )
// ],
// ),
// );
// final result2 = generator.generate(
// code: carsService,
// className: 'CarsService',
// fileName: 'cars_service',
// options: GeneratorOptions(
// inputFolder: '',
// outputFolder: '',
// defaultHeaderValuesMap: [
// DefaultHeaderValueMap(
// defaultValue: '120',
// headerName: 'id',
// ),
// ],
// includePaths: [
// 'car'
// ]),
// );
// expect(result2, contains('Future<chopper.Response<CarModel>>'));
// expect(result, contains('Future<chopper.Response<CarModel>> carsGet'));
// expect(result, contains('Future<chopper.Response<CarModel>> carsPost'));
// expect(
// result,
// contains(
// 'Future<chopper.Response<CarModel>> carsAdditionalPut({@Body() required Object? body});'));
// });
});
}

View File

@ -0,0 +1,796 @@
const ref = '\$ref';
const carsService = '''
{
"openapi": "3.0.0",
"info": {
"title": "Swagger title",
"description": "Swagger description",
"version": "1.0.0"
},
"paths": {
"/cars": {
"put": {
"summary": "Sends car to server",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded1",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"post": {
"summary": "Sends car to server",
"requestBody": {
"description": "Car model",
"required": true,
"$ref": "#/components/schemas/CarModel"
},
"responses": {
"200": {
"description": "Car successfuly loaded2",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"get": {
"summary": "Get car by id and type",
"parameters": [
{
"name": "id",
"type": "String",
"in": "header",
"required": true,
"description": "This parameter is needed to set id of car"
},
{
"name": "type",
"type": "enum",
"in": "query",
"items": {
"type": "string"
},
"required": true,
"description": "This parameter is needed to set type of car"
}
],
"responses": {
"200": {
"description": "Car received",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
}
},
"/cars/additional": {
"get": {
"summary": "Sends binary to server",
"parameters": [
{
"name": "id",
"type": "String",
"in": "header",
"required": true
},
{
"name": "carEnumType",
"in": "query",
"type": "object",
"schema": {
"$ref": "#/components/schemas/CarType"
}
},
{
"name": "timestamp",
"type": "String",
"in": "query",
"required": false
}
],
"responses": {
"200": {
"description": "Car successfuly loaded3",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"put": {
"summary": "Sends binary to server",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"format": "binary"
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded4",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"post": {
"summary": "Sends list of cars to server",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded5",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
}
},
"/cars/optionalBody": {
"post": {
"summary": "Its needed to test optionalBody",
"responses": {
"200": {
"description": "Car successfuly loaded6",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"put": {
"summary": "Its needed to test cases with form data and body in parameter",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CarType"
}
}
}
}
},
"parameters": [
{
"name": "body",
"type": "String",
"in": "body",
"schema": {
"$ref": "#/components/schemas/CarType"
}
},
{
"name": "formData",
"in": "formData",
"type": "object",
"schema": {
"$ref": "#/components/schemas/CarType"
}
},
{
"name": "someEnumParameter",
"in": "query",
"items": {
"enum": [
"one",
"two",
"three"
]
}
},
{
"name": "someEnumParameterRef",
"in": "query",
"items": {
"$ref": "#/components/schemas/CarType"
}
},
{
"name": "someNotEnumParameter",
"in": "query",
"items": {
"$ref": "#/components/schemas/CarModel"
}
},
{
"name": "parameterWithSchemaItemsRef",
"in": "query",
"schema": {
"items": {
"$ref": "#/components/schemas/CarModel"
}
}
},
{
"name": "parameterWithSchemaItemsEnumRef",
"in": "query",
"schema": {
"items": {
"$ref": "#/components/schemas/CarType"
}
}
},
{
"name": "parameterWithSchemaRefNotEnum",
"in": "query",
"schema": {
"$ref": "#/components/schemas/CarModel"
}
},
{
"name": "parameterWithSchemaRefArray",
"in": "query",
"schema": {
"type": "array",
"$ref": "#/components/schemas/CarModel"
}
},
{
"name": "parameterWithSchemaTypeArray",
"in": "query",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "parameterWithSchemaAnyOf",
"in": "query",
"schema": {
"anyOf": [
{
"type": "string"
}
]
}
},
{
"name": "somethingReallyBad",
"in": "query"
}
],
"responses": {
"200": {
"description": "Car successfuly loaded7",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
}
},
"/cars/postCarExamples": {
"post": {
"summary": "Its needed to test optionalBody",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"items": {
"$ref": "#/components/schemas/CarType"
}
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded8",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
}
},
"/cars/schemaRefBody": {
"get": {
"summary": "Overwritten response",
"responses": {
"202": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarType"
}
}
}
}
}
},
"post": {
"summary": "Its needed to test optionalBody",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarType"
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded9",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
},
"put": {
"summary": "Its needed to test optionalBody",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarType"
}
}
}
},
"responses": {
"202": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarType"
}
}
}
}
}
}
},
"/cars/returnTypeTests": {
"get": {
"summary": "Overwritten response",
"responses": {
"202": {
"description": "Success",
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "enum",
"name": "String",
"items": {
"type": "string"
}
}
}
}
}
}
},
"post": {
"summary": "Overwritten response POST",
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CarType"
}
}
}
}
},
"put": {
"summary": "Overwritten response POST",
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "String"
}
}
}
}
},
"/cars/returnTypeSchema": {
"get": {
"summary": "Return type schema",
"responses": {
"200": {
"description": "Success",
"schema": {
"items": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
},
"post": {
"summary": "Return type schema",
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/components/responses/CarModelResponse"
}
}
}
},
"put": {
"summary": "Return type schema",
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/components/responses/CarModel"
}
}
}
}
},
"/cars/returnTypeOriginalRef": {
"get": {
"summary": "Return type originalRef",
"responses": {
"200": {
"description": "Success",
"schema": {
"originalRef": "CarModel"
}
}
}
}
},
"/cars/returnTypeByContent": {
"get": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"$ref": "#/components/responses/CarModel"
}
}
}
}
},
"put": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ListOfCars"
}
}
}
}
}
},
"post": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success with original ref",
"schema": {
"items": {
"originalRef": "CarModel"
}
},
"content": {
"application/json": {
"responseType": "array"
}
}
}
}
}
},
"/cars/returnTypeContentItemsRef": {
"get": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"items": {
"$ref": "#/components/responses/CarModel"
}
}
}
}
}
},
"put": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/responses/CarModel"
}
}
}
}
}
}
},
"post": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/cars/veryBadResponse": {
"get": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {}
}
}
}
},
"put": {
"summary": "Return type by content",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"responseType": "string"
}
}
}
}
}
},
"/cars/responseWithAbsendRef": {
"put": {
"summary": "Sends car to server not existing ref",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
},
"responses": {
"200": {
"description": "Car successfuly loaded1",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarMNotExistingCarModelodel"
}
}
}
}
}
},
"post": {
"summary": "Request body with default type",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CarModelSimple"
}
}
}
}
},
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/components/responses/CarType"
}
}
}
}
},
"/cars/oneMoreRequestBody": {
"put": {
"summary": "Sends car to server",
"requestBody": {
"description": "Car model",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModelSimple"
}
}
}
},
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/components/responses/NotExistingCarResponse"
}
}
}
}
}
},
"components": {
"schemas": {
"CarModelSimple": {
"type": "string"
},
"CarModel": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "enum",
"name": "String",
"items": {
"type": "string"
}
}
}
},
"ListOfCars": {
"type": "array",
"items": {
"type": "String"
}
},
"CarType": {
"type": "string",
"enum": [
"one",
"two",
"three"
]
}
},
"requestBodies": {
"CarModel": {
"type": "object",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
},
"responses": {
"CarModelResponse": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CarModel"
}
}
}
}
}
}
}
''';

View File

@ -1,12 +1,88 @@
# targets:
# $default:
# builders:
# injectable_generator:injectable_builder:
# options:
# auto_register: true
# # auto registers any class with a name matches the given pattern
# class_name_pattern:
# "Service$|Repository$|Bloc$|UseCases$"
# # auto registers any class inside a file with a
# # name matches the given pattern
# #file_name_pattern: "_service$|_repository$|_bloc$"
targets:
$default:
sources:
- lib/**
- swaggers/**
- swaggers2/**
- swagger_examples/**
- $package$
builders:
# copy_with_extension_gen:
# enabled: true
# options:
# copy_with_null: true # default is false
# # skip_fields: true
injectable_generator:injectable_builder:
options:
auto_register: true
# auto registers any class with a name matches the given pattern
class_name_pattern:
"Service$|Repository$|Bloc$|UseCases$"
"Service$|Bloc$|UseCases$"
# auto registers any class inside a file with a
# name matches the given pattern
#file_name_pattern: "_service$|_repository$|_bloc$"
#file_name_pattern: "_service$|_repository$|_bloc$"
swagger_dart_code_generator:
options:
input_folder: "lib/features/repositories/"
output_folder: "lib/features/repositories/"
use_inheritance: false
with_converter: true
use_default_null_for_lists: false
build_only_models: false
separate_models: true
enums_case_sensitive: false
ignore_headers: true
use_required_attribute_for_headers: false
include_if_null: true
default_api_version: '1.0'
url_parterns:
# - "/public/"
custom_api_version:
- version: "2.0"
urls: "/api/exam/v{version}/public/ExamPackage/GetList,/api/exam/v{version}/public/ExamPackage/GetListIsBuy,/api/exam/v{version}/public/Competition/GetAllCompetitionForDashBoard,/api/exam/v{version}/public/HomePage/GetData,/api/exam/v{version}/public/Exam/GetCategoryCountExam,/api/exam/v{version}/public/HomePage/GetListDataView"
exclude_params:
- "block"
- "blockId"
- "version"
include_paths:
exclude_paths:
- "/api/v1/captcha/refresh/refresh"
- "/api/v1/captcha/show/show"
- "/weatherforecast/get"
response_override_value_map:
request_override_value_map:
# default_header_values_map:
# - header_name: "X-Entitlements-Token"
# default_value: "X-Entitlements-Token"
# - header_name: "X-Cus"
# default_value: "X-Cus"
# - url: "/api/system/v1.0/public/Notify/GetList"
# method: get
# param_name: ""
# overridden_value: "NotifyGetListRequestModel"
custom_model_path:
- 'package:baseproject/features/model/index.dart'
# - 'package:eschool/core/model/index.dart'
# default_values_map:
# - type_name: String
# default_value: ""
# - type_name: int
# default_value: '0'
# - type_name: double
# default_value: '0'
# - type_name: bool
# default_value: 'false'

View File

@ -0,0 +1,13 @@
export 'injection.dart';
export 'injection.config.dart';
export 'custom_interceptor.dart';
export 'utils.dart';
export 'message.dart';
export 'shared_preferences/local_storage_manager.dart';
export 'loading.dart';
export 'common_module.dart';
export 'bloc/bloc_index.dart';
export 'bloc/base_stateful.dart';
export 'bloc/base_state.dart';
export 'bloc/base_cubit.dart';
export 'validators.dart';

View File

@ -1,10 +1,17 @@
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
import 'package:baseproject/core/constants/index.dart';
import 'package:baseproject/features/repositories/hra_repository.dart';
import 'package:dio/dio.dart';
final GetIt getItSuper = GetIt.instance;
@injectableInit
void configureInjection() {
$initGetIt(getItSuper);
getItSuper
.registerSingleton<HraRepository>(HraRepository(Dio(), baseUrl: kDebugMode ? ApiPath.hra : ApiPathRelease.hra));
}

View File

@ -377,4 +377,97 @@ class ConstantWidget {
topRight: Radius.circular(28),
),
);
static ElevatedButton buildPrimaryButton({
VoidCallback? onPressed,
String text = "",
EdgeInsets? padding,
TextStyle? style,
Widget? child,
double? textScaleFactor,
}) =>
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: CustomColor.bgPriSolid,
padding: padding,
),
child: child ??
Text(
text,
style: (style ?? textStyleBodyDefaultBold).copyWith(color: CustomColor.kTextWhiteColor),
textAlign: TextAlign.center,
textScaleFactor: textScaleFactor,
),
onPressed: onPressed,
);
static ElevatedButton buildPrimaryButtonWithIcon(
{VoidCallback? onPressed,
required String text,
required Widget icon,
EdgeInsets? padding,
TextStyle? style}) =>
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: CustomColor.bgPriSolid,
padding: padding,
),
child: Row(
children: [
Expanded(
child: Text(
text,
style: (style ?? textStyleBodyDefaultBold).copyWith(color: CustomColor.kTextWhiteColor),
textAlign: TextAlign.center,
),
),
icon
],
),
onPressed: onPressed,
);
static ElevatedButton buildSecondButtonWithIcon(
{VoidCallback? onPressed, required String text, required Widget icon, EdgeInsets? padding}) =>
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffFDF0E1),
padding: padding,
),
child: Row(
children: [
Expanded(
child: Text(
text,
style: textStyleBodyDefaultBold.copyWith(color: CustomColor.darkSecondColor),
textAlign: TextAlign.center,
),
),
icon
],
),
onPressed: onPressed,
);
static ElevatedButton buildDefaultButtonWithIcon(
{VoidCallback? onPressed, required String text, required Widget icon, EdgeInsets? padding}) =>
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: CustomColor.bgSecondSolid,
padding: padding,
),
child: Row(
children: [
Expanded(
child: Text(
text,
style: textStyleBodyDefaultBold.copyWith(color: CustomColor.kTextWhiteColor),
textAlign: TextAlign.center,
),
),
icon
],
),
onPressed: onPressed,
);
}

View File

@ -14,3 +14,7 @@ export 'radio/custom_radio_list.dart';
export 'grid_view/custom_gridview.dart';
export 'listview/custom_listview.dart';
export 'custom_pull_to_refresh.dart';
export 'date/date_time_picker.dart';
export 'alice.dart';
export 'tab/custom_tab.dart';
export 'switch/custom_switch_list_tile.dart';

View File

@ -0,0 +1,7 @@
class ApiPath {
static const String hra = 'https://api.hra.edu.vn';
}
class ApiPathRelease {
static const String hra = 'https://api.hra.edu.vn';
}

View File

@ -0,0 +1,4 @@
export 'api_path.dart';
export 'storage_key.dart';
export 'constant_string.dart';
export 'validate_keys.dart';

View File

@ -17,6 +17,8 @@ class CustomColor {
static const Color colorButtonDefault = Color(0xffE1E4FF);
static const Color colorButtonBold = Color(0xff5E67BA);
static Color colorTextButtonDefault = colorButtonBold;
static const Color bgPriSolid = Color(0xff2fc3a9);
static const Color bgSecondSolid = Color(0xfff19a34);
//barrierColor
static Color barrierColor = const Color(0xff1B1E37).withValues(alpha: 0.9);

View File

@ -0,0 +1 @@
export 'login_dto.dart';

View File

@ -0,0 +1,27 @@
class LoginDto {
LoginDto({
this.userName,
this.password,
this.rememberMe = false,
this.captchaText,
this.captchaToken,
this.captchaInputText,
});
String? userName;
String? password;
bool rememberMe;
String? captchaText;
String? captchaToken;
String? captchaInputText;
Map<String, dynamic> toJson() => {
'UserName': userName,
'Password': password,
'RememberMe': rememberMe,
'CaptchaText': captchaText,
'CaptchaToken': captchaToken,
'CaptchaInputText': captchaInputText,
};
}

View File

@ -0,0 +1,157 @@
import 'package:baseproject/core/common/index.dart';
import 'package:baseproject/core/components/index.dart';
import 'package:baseproject/features/model/login_dto.dart';
import 'package:baseproject/features/usecases/user_use_cases.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final GlobalKey<FormBuilderState> _formKey = GlobalKey<FormBuilderState>();
bool _isLoading = false;
String? _error;
bool _rememberMe = false;
Future<void> _onSubmit() async {
final formState = _formKey.currentState;
if (formState == null) return;
if (!formState.saveAndValidate()) {
return;
}
final value = formState.value;
final dto = LoginDto(
userName: value['userName'] as String?,
password: value['password'] as String?,
rememberMe: _rememberMe,
);
setState(() {
_isLoading = true;
_error = null;
});
final userUseCases = getItSuper<UserUseCases>();
final result = await userUseCases.loginAccount(dto);
result.fold(
(l) => setState(() {
_error = l;
_isLoading = false;
}),
(r) {
setState(() {
_isLoading = false;
});
// TODO: điều hướng sang màn hình chính sau khi login thành công
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Đăng nhập'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: FormBuilder(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (_error != null)
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Text(
_error!,
style: const TextStyle(color: Colors.red),
),
),
FormControl(
labelText: 'Tên đăng nhập',
isShowTextRequire: true,
child: TextFormField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Nhập tên đăng nhập',
),
validator: FormBuilderValidators.required<String>(
context,
),
onSaved: (value) {
_formKey.currentState?.setInternalFieldValue(
'userName',
value,
isUpdateState: false,
);
},
),
),
const SizedBox(height: 16),
FormControl(
labelText: 'Mật khẩu',
isShowTextRequire: true,
child: TextFormField(
obscureText: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Nhập mật khẩu',
),
validator: FormBuilderValidators.required<String>(
context,
),
onSaved: (value) {
_formKey.currentState?.setInternalFieldValue(
'password',
value,
isUpdateState: false,
);
},
),
),
const SizedBox(height: 8),
Row(
children: <Widget>[
Checkbox(
value: _rememberMe,
onChanged: (v) {
setState(() {
_rememberMe = v ?? false;
});
},
),
const Text('Ghi nhớ đăng nhập'),
],
),
const SizedBox(height: 24),
SizedBox(
height: 48,
child: ElevatedButton(
onPressed: _isLoading ? null : _onSubmit,
child: _isLoading
? const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
)
: const Text('Đăng nhập'),
),
),
],
),
),
),
),
);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,913 @@
import 'package:json_annotation/json_annotation.dart';
enum AssignExamStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $AssignExamStatusEnumMap = {
AssignExamStatusEnum.value_0: '0',
AssignExamStatusEnum.value_1: '1',
AssignExamStatusEnum.value_2: '2',
AssignExamStatusEnum.swaggerGeneratedUnknown: ''
};
enum AssignExamTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $AssignExamTypeEnumMap = {
AssignExamTypeEnum.value_0: '0',
AssignExamTypeEnum.value_1: '1',
AssignExamTypeEnum.value_2: '2',
AssignExamTypeEnum.swaggerGeneratedUnknown: ''
};
enum AssignExamUserStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $AssignExamUserStatusEnumMap = {
AssignExamUserStatusEnum.value_0: '0',
AssignExamUserStatusEnum.value_1: '1',
AssignExamUserStatusEnum.value_2: '2',
AssignExamUserStatusEnum.swaggerGeneratedUnknown: ''
};
enum AttendanceStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $AttendanceStatusEnumMap = {
AttendanceStatusEnum.value_1: '1',
AttendanceStatusEnum.value_2: '2',
AttendanceStatusEnum.value_3: '3',
AttendanceStatusEnum.value_4: '4',
AttendanceStatusEnum.swaggerGeneratedUnknown: ''
};
enum ClassListSearchTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3
}
const $ClassListSearchTypeEnumMap = {
ClassListSearchTypeEnum.value_0: '0',
ClassListSearchTypeEnum.value_1: '1',
ClassListSearchTypeEnum.value_2: '2',
ClassListSearchTypeEnum.value_3: '3',
ClassListSearchTypeEnum.swaggerGeneratedUnknown: ''
};
enum ClassStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ClassStatusEnumMap = {
ClassStatusEnum.value_1: '1',
ClassStatusEnum.value_2: '2',
ClassStatusEnum.swaggerGeneratedUnknown: ''
};
enum ClassTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ClassTypeEnumMap = {
ClassTypeEnum.value_1: '1',
ClassTypeEnum.value_2: '2',
ClassTypeEnum.swaggerGeneratedUnknown: ''
};
enum ClassUserRoleEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3
}
const $ClassUserRoleEnumMap = {
ClassUserRoleEnum.value_0: '0',
ClassUserRoleEnum.value_1: '1',
ClassUserRoleEnum.value_2: '2',
ClassUserRoleEnum.value_3: '3',
ClassUserRoleEnum.swaggerGeneratedUnknown: ''
};
enum ClassUserStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $ClassUserStatusEnumMap = {
ClassUserStatusEnum.value_1: '1',
ClassUserStatusEnum.value_2: '2',
ClassUserStatusEnum.value_3: '3',
ClassUserStatusEnum.value_4: '4',
ClassUserStatusEnum.swaggerGeneratedUnknown: ''
};
enum CommonStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $CommonStatusEnumMap = {
CommonStatusEnum.value_1: '1',
CommonStatusEnum.value_2: '2',
CommonStatusEnum.swaggerGeneratedUnknown: ''
};
enum ConsultationStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3
}
const $ConsultationStatusEnumMap = {
ConsultationStatusEnum.value_0: '0',
ConsultationStatusEnum.value_1: '1',
ConsultationStatusEnum.value_2: '2',
ConsultationStatusEnum.value_3: '3',
ConsultationStatusEnum.swaggerGeneratedUnknown: ''
};
enum ContactStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3
}
const $ContactStatusEnumMap = {
ContactStatusEnum.value_0: '0',
ContactStatusEnum.value_1: '1',
ContactStatusEnum.value_2: '2',
ContactStatusEnum.value_3: '3',
ContactStatusEnum.swaggerGeneratedUnknown: ''
};
enum ErrorCodeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('100')
value_100,
@JsonValue('101')
value_101,
@JsonValue('102')
value_102,
@JsonValue('103')
value_103,
@JsonValue('104')
value_104,
@JsonValue('105')
value_105,
@JsonValue('106')
value_106,
@JsonValue('107')
value_107,
@JsonValue('108')
value_108,
@JsonValue('109')
value_109,
@JsonValue('110')
value_110,
@JsonValue('111')
value_111,
@JsonValue('112')
value_112,
@JsonValue('113')
value_113,
@JsonValue('114')
value_114,
@JsonValue('115')
value_115,
@JsonValue('116')
value_116,
@JsonValue('117')
value_117,
@JsonValue('118')
value_118,
@JsonValue('119')
value_119,
@JsonValue('120')
value_120,
@JsonValue('121')
value_121,
@JsonValue('122')
value_122,
@JsonValue('123')
value_123,
@JsonValue('200')
value_200,
@JsonValue('201')
value_201,
@JsonValue('202')
value_202,
@JsonValue('203')
value_203,
@JsonValue('204')
value_204,
@JsonValue('205')
value_205,
@JsonValue('206')
value_206,
@JsonValue('207')
value_207,
@JsonValue('208')
value_208,
@JsonValue('226')
value_226,
@JsonValue('300')
value_300,
@JsonValue('301')
value_301,
@JsonValue('302')
value_302,
@JsonValue('303')
value_303,
@JsonValue('304')
value_304,
@JsonValue('305')
value_305,
@JsonValue('306')
value_306,
@JsonValue('307')
value_307,
@JsonValue('308')
value_308,
@JsonValue('400')
value_400,
@JsonValue('401')
value_401,
@JsonValue('402')
value_402,
@JsonValue('403')
value_403,
@JsonValue('404')
value_404,
@JsonValue('405')
value_405,
@JsonValue('406')
value_406,
@JsonValue('407')
value_407,
@JsonValue('408')
value_408,
@JsonValue('409')
value_409,
@JsonValue('410')
value_410,
@JsonValue('411')
value_411,
@JsonValue('412')
value_412,
@JsonValue('413')
value_413,
@JsonValue('414')
value_414,
@JsonValue('415')
value_415,
@JsonValue('416')
value_416,
@JsonValue('417')
value_417,
@JsonValue('421')
value_421,
@JsonValue('422')
value_422,
@JsonValue('423')
value_423,
@JsonValue('424')
value_424,
@JsonValue('426')
value_426,
@JsonValue('428')
value_428,
@JsonValue('429')
value_429,
@JsonValue('431')
value_431,
@JsonValue('451')
value_451,
@JsonValue('500')
value_500,
@JsonValue('501')
value_501,
@JsonValue('502')
value_502,
@JsonValue('503')
value_503,
@JsonValue('504')
value_504,
@JsonValue('505')
value_505,
@JsonValue('506')
value_506,
@JsonValue('507')
value_507,
@JsonValue('508')
value_508,
@JsonValue('510')
value_510,
@JsonValue('511')
value_511,
@JsonValue('512')
value_512,
@JsonValue('513')
value_513,
@JsonValue('-1')
value_1
}
const $ErrorCodeEnumMap = {
ErrorCodeEnum.value_0: '0',
ErrorCodeEnum.value_100: '100',
ErrorCodeEnum.value_101: '101',
ErrorCodeEnum.value_102: '102',
ErrorCodeEnum.value_103: '103',
ErrorCodeEnum.value_104: '104',
ErrorCodeEnum.value_105: '105',
ErrorCodeEnum.value_106: '106',
ErrorCodeEnum.value_107: '107',
ErrorCodeEnum.value_108: '108',
ErrorCodeEnum.value_109: '109',
ErrorCodeEnum.value_110: '110',
ErrorCodeEnum.value_111: '111',
ErrorCodeEnum.value_112: '112',
ErrorCodeEnum.value_113: '113',
ErrorCodeEnum.value_114: '114',
ErrorCodeEnum.value_115: '115',
ErrorCodeEnum.value_116: '116',
ErrorCodeEnum.value_117: '117',
ErrorCodeEnum.value_118: '118',
ErrorCodeEnum.value_119: '119',
ErrorCodeEnum.value_120: '120',
ErrorCodeEnum.value_121: '121',
ErrorCodeEnum.value_122: '122',
ErrorCodeEnum.value_123: '123',
ErrorCodeEnum.value_200: '200',
ErrorCodeEnum.value_201: '201',
ErrorCodeEnum.value_202: '202',
ErrorCodeEnum.value_203: '203',
ErrorCodeEnum.value_204: '204',
ErrorCodeEnum.value_205: '205',
ErrorCodeEnum.value_206: '206',
ErrorCodeEnum.value_207: '207',
ErrorCodeEnum.value_208: '208',
ErrorCodeEnum.value_226: '226',
ErrorCodeEnum.value_300: '300',
ErrorCodeEnum.value_301: '301',
ErrorCodeEnum.value_302: '302',
ErrorCodeEnum.value_303: '303',
ErrorCodeEnum.value_304: '304',
ErrorCodeEnum.value_305: '305',
ErrorCodeEnum.value_306: '306',
ErrorCodeEnum.value_307: '307',
ErrorCodeEnum.value_308: '308',
ErrorCodeEnum.value_400: '400',
ErrorCodeEnum.value_401: '401',
ErrorCodeEnum.value_402: '402',
ErrorCodeEnum.value_403: '403',
ErrorCodeEnum.value_404: '404',
ErrorCodeEnum.value_405: '405',
ErrorCodeEnum.value_406: '406',
ErrorCodeEnum.value_407: '407',
ErrorCodeEnum.value_408: '408',
ErrorCodeEnum.value_409: '409',
ErrorCodeEnum.value_410: '410',
ErrorCodeEnum.value_411: '411',
ErrorCodeEnum.value_412: '412',
ErrorCodeEnum.value_413: '413',
ErrorCodeEnum.value_414: '414',
ErrorCodeEnum.value_415: '415',
ErrorCodeEnum.value_416: '416',
ErrorCodeEnum.value_417: '417',
ErrorCodeEnum.value_421: '421',
ErrorCodeEnum.value_422: '422',
ErrorCodeEnum.value_423: '423',
ErrorCodeEnum.value_424: '424',
ErrorCodeEnum.value_426: '426',
ErrorCodeEnum.value_428: '428',
ErrorCodeEnum.value_429: '429',
ErrorCodeEnum.value_431: '431',
ErrorCodeEnum.value_451: '451',
ErrorCodeEnum.value_500: '500',
ErrorCodeEnum.value_501: '501',
ErrorCodeEnum.value_502: '502',
ErrorCodeEnum.value_503: '503',
ErrorCodeEnum.value_504: '504',
ErrorCodeEnum.value_505: '505',
ErrorCodeEnum.value_506: '506',
ErrorCodeEnum.value_507: '507',
ErrorCodeEnum.value_508: '508',
ErrorCodeEnum.value_510: '510',
ErrorCodeEnum.value_511: '511',
ErrorCodeEnum.value_512: '512',
ErrorCodeEnum.value_513: '513',
ErrorCodeEnum.value_1: '-1',
ErrorCodeEnum.swaggerGeneratedUnknown: ''
};
enum ExamFileChoiceTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ExamFileChoiceTypeEnumMap = {
ExamFileChoiceTypeEnum.value_1: '1',
ExamFileChoiceTypeEnum.value_2: '2',
ExamFileChoiceTypeEnum.swaggerGeneratedUnknown: ''
};
enum ExamFormatEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ExamFormatEnumMap = {
ExamFormatEnum.value_1: '1',
ExamFormatEnum.value_2: '2',
ExamFormatEnum.swaggerGeneratedUnknown: ''
};
enum ExamStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $ExamStatusEnumMap = {
ExamStatusEnum.value_1: '1',
ExamStatusEnum.value_2: '2',
ExamStatusEnum.value_3: '3',
ExamStatusEnum.value_4: '4',
ExamStatusEnum.swaggerGeneratedUnknown: ''
};
enum ExamTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ExamTypeEnumMap = {
ExamTypeEnum.value_0: '0',
ExamTypeEnum.value_1: '1',
ExamTypeEnum.value_2: '2',
ExamTypeEnum.swaggerGeneratedUnknown: ''
};
enum FileStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4,
@JsonValue('5')
value_5,
@JsonValue('6')
value_6
}
const $FileStatusEnumMap = {
FileStatusEnum.value_0: '0',
FileStatusEnum.value_1: '1',
FileStatusEnum.value_2: '2',
FileStatusEnum.value_3: '3',
FileStatusEnum.value_4: '4',
FileStatusEnum.value_5: '5',
FileStatusEnum.value_6: '6',
FileStatusEnum.swaggerGeneratedUnknown: ''
};
enum LessonTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $LessonTypeEnumMap = {
LessonTypeEnum.value_1: '1',
LessonTypeEnum.value_2: '2',
LessonTypeEnum.value_3: '3',
LessonTypeEnum.value_4: '4',
LessonTypeEnum.swaggerGeneratedUnknown: ''
};
enum LocalityStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $LocalityStatusEnumMap = {
LocalityStatusEnum.value_0: '0',
LocalityStatusEnum.value_1: '1',
LocalityStatusEnum.value_2: '2',
LocalityStatusEnum.swaggerGeneratedUnknown: ''
};
enum LocalityTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3
}
const $LocalityTypeEnumMap = {
LocalityTypeEnum.value_1: '1',
LocalityTypeEnum.value_2: '2',
LocalityTypeEnum.value_3: '3',
LocalityTypeEnum.swaggerGeneratedUnknown: ''
};
enum ModuleEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4,
@JsonValue('5')
value_5,
@JsonValue('6')
value_6,
@JsonValue('7')
value_7,
@JsonValue('8')
value_8,
@JsonValue('9')
value_9,
@JsonValue('10')
value_10,
@JsonValue('11')
value_11,
@JsonValue('12')
value_12,
@JsonValue('13')
value_13,
@JsonValue('98')
value_98,
@JsonValue('99')
value_99
}
const $ModuleEnumMap = {
ModuleEnum.value_1: '1',
ModuleEnum.value_2: '2',
ModuleEnum.value_3: '3',
ModuleEnum.value_4: '4',
ModuleEnum.value_5: '5',
ModuleEnum.value_6: '6',
ModuleEnum.value_7: '7',
ModuleEnum.value_8: '8',
ModuleEnum.value_9: '9',
ModuleEnum.value_10: '10',
ModuleEnum.value_11: '11',
ModuleEnum.value_12: '12',
ModuleEnum.value_13: '13',
ModuleEnum.value_98: '98',
ModuleEnum.value_99: '99',
ModuleEnum.swaggerGeneratedUnknown: ''
};
enum ObjectTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ObjectTypeEnumMap = {
ObjectTypeEnum.value_0: '0',
ObjectTypeEnum.value_1: '1',
ObjectTypeEnum.value_2: '2',
ObjectTypeEnum.swaggerGeneratedUnknown: ''
};
enum OrderStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4,
@JsonValue('5')
value_5
}
const $OrderStatusEnumMap = {
OrderStatusEnum.value_0: '0',
OrderStatusEnum.value_1: '1',
OrderStatusEnum.value_2: '2',
OrderStatusEnum.value_3: '3',
OrderStatusEnum.value_4: '4',
OrderStatusEnum.value_5: '5',
OrderStatusEnum.swaggerGeneratedUnknown: ''
};
enum ProductReviewStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ProductReviewStatusEnumMap = {
ProductReviewStatusEnum.value_0: '0',
ProductReviewStatusEnum.value_1: '1',
ProductReviewStatusEnum.value_2: '2',
ProductReviewStatusEnum.swaggerGeneratedUnknown: ''
};
enum ProductTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $ProductTypeEnumMap = {
ProductTypeEnum.value_0: '0',
ProductTypeEnum.value_1: '1',
ProductTypeEnum.value_2: '2',
ProductTypeEnum.swaggerGeneratedUnknown: ''
};
enum QuestionLevelEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $QuestionLevelEnumMap = {
QuestionLevelEnum.value_1: '1',
QuestionLevelEnum.value_2: '2',
QuestionLevelEnum.value_3: '3',
QuestionLevelEnum.value_4: '4',
QuestionLevelEnum.swaggerGeneratedUnknown: ''
};
enum QuestionStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $QuestionStatusEnumMap = {
QuestionStatusEnum.value_0: '0',
QuestionStatusEnum.value_1: '1',
QuestionStatusEnum.value_2: '2',
QuestionStatusEnum.value_3: '3',
QuestionStatusEnum.value_4: '4',
QuestionStatusEnum.swaggerGeneratedUnknown: ''
};
enum SchoolStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $SchoolStatusEnumMap = {
SchoolStatusEnum.value_0: '0',
SchoolStatusEnum.value_1: '1',
SchoolStatusEnum.value_2: '2',
SchoolStatusEnum.swaggerGeneratedUnknown: ''
};
enum SessionStatusEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4
}
const $SessionStatusEnumMap = {
SessionStatusEnum.value_1: '1',
SessionStatusEnum.value_2: '2',
SessionStatusEnum.value_3: '3',
SessionStatusEnum.value_4: '4',
SessionStatusEnum.swaggerGeneratedUnknown: ''
};
enum UserExamResultStatus {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2
}
const $UserExamResultStatusMap = {
UserExamResultStatus.value_1: '1',
UserExamResultStatus.value_2: '2',
UserExamResultStatus.swaggerGeneratedUnknown: ''
};
enum UserTypeEnum {
@JsonValue('swaggerGeneratedUnknown')
swaggerGeneratedUnknown,
@JsonValue('0')
value_0,
@JsonValue('1')
value_1,
@JsonValue('2')
value_2,
@JsonValue('3')
value_3,
@JsonValue('4')
value_4,
@JsonValue('5')
value_5,
@JsonValue('6')
value_6,
@JsonValue('7')
value_7
}
const $UserTypeEnumMap = {
UserTypeEnum.value_0: '0',
UserTypeEnum.value_1: '1',
UserTypeEnum.value_2: '2',
UserTypeEnum.value_3: '3',
UserTypeEnum.value_4: '4',
UserTypeEnum.value_5: '5',
UserTypeEnum.value_6: '6',
UserTypeEnum.value_7: '7',
UserTypeEnum.swaggerGeneratedUnknown: ''
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
import 'package:baseproject/features/model/index.dart';
import 'package:baseproject/features/repositories/hra_repository.dart';
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
@lazySingleton
class UserUseCases {
final HraRepository _hraRepository;
UserUseCases(this._hraRepository);
Future<Either<String, LoginResponseDto>> loginAccount(LoginDto request) async {
try {
final result = await _hraRepository.accountLogin(request);
if (result.data == null) {
return Left<String, LoginResponseDto>(result.message ?? 'Login failed');
}
return Right<String, LoginResponseDto>(result.data!);
} catch (ex) {
return Left<String, LoginResponseDto>(ex.toString());
}
}
Future<Either<String, DNTCaptchaApiResponse>> getCaptcha() async {
try {
final result = await _hraRepository.accountCaptcha();
return Right<String, DNTCaptchaApiResponse>(result);
} catch (ex) {
return Left<String, DNTCaptchaApiResponse>(ex.toString());
}
}
}

View File

@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.16.1 <3.0.0"
sdk: ">=3.3.0 <4.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@ -57,6 +57,7 @@ dependencies:
file_picker: ^8.1.6
flutter_staggered_grid_view: ^0.7.0
pull_to_refresh: ^2.0.0
dartz: ^0.10.1
dependency_overrides:
watcher: ^1.1.0
@ -65,14 +66,18 @@ dependency_overrides:
pub_semver: 2.1.4
win32: 5.13.0
http: ^1.4.0
# Dart 3.5+ chỉ có frontend_server_aot; package 3.x tìm JIT snapshot → ép dùng 4.x
frontend_server_client: ^4.0.0
dev_dependencies:
flutter_test:
sdk: flutter
injectable_generator:
build_runner: 2.3.3
retrofit_generator: 4.2.0
json_serializable: ^6.3.0
build_runner: ^2.4.0
retrofit_generator: ^4.2.0
json_serializable: ^6.8.0
swagger_dart_code_generator:
path: ./api_automatic/

14
update_open_api.ps1 Normal file
View File

@ -0,0 +1,14 @@
# Đảm bảo dùng Dart của Flutter (tránh lỗi frontend_server.dart.snapshot trên Dart 3.5+)
$flutterRoot = if ($env:FLUTTER_ROOT) { $env:FLUTTER_ROOT } else { (Get-Command flutter -ErrorAction SilentlyContinue).Source | ForEach-Object { Split-Path (Split-Path $_) } }
if ($flutterRoot) {
$env:Path = "$flutterRoot\bin\cache\dart-sdk\bin;$flutterRoot\bin;$env:Path"
}
# Tải các file JSON về thư mục tương ứng
Invoke-WebRequest -Uri "https://api.hra.edu.vn/swagger/v1/swagger.json" -OutFile "./lib/features/repositories/hra_repository.json"
# Chạy build_runner
dart run build_runner build --delete-conflicting-outputs
# Xóa các file JSON đã tải về
Remove-Item "./lib/features/repositories/hra_repository.json"

4
update_open_api.sh Normal file
View File

@ -0,0 +1,4 @@
curl -s https://api.hra.edu.vn/swagger/v1/swagger.json -o ./lib/features/repositories/hra_repository.json
flutter pub run build_runner build --delete-conflicting-outputs
rm ./lib/features/repositories/hra_repository.json