This plugin was originally designed for use by the OpenAPi v3 Maven Plugin, but works with the command line generator and the Gradle plugin. it generates excellent Dart code and uses Dio.
There is an article on Medium discussing this plugin.
-
Irina Southwell (nee Капрельянц Ирина), Principal Engineer (https://www.linkedin.com/in/irina-southwell-9727a422/)
-
Richard Vowles, Software Developer (https://www.linkedin.com/in/richard-vowles-72035193/)
-
4.2 - if you directly use the Type Transformers for enums, this is a breaking change. They have changed to extensions and have been slightly remodeled based on Robert’s inlining work. The whole deserialisation mechanism has changed particluarly for lists and maps because it wasn’t able to cope more than one level deep with lists and maps (issue #19). The date format now serialises directly properly, but not in lists.
-
4.1 - support for OpenAPI v5, released 2020/12/21. Next release will support null types in Dart. Please note that with the move to 4.1, form models are by default NOT generated, so your parameters for methods calling forms won’t work. You need to set a global property called
skipFormModels
to false. In Maven this is in the configuration
<globalProperties>
<skipFormModels>false</skipFormModels>
</globalProperties>
-
3.10 - support extension methods for mapping between enum names and types
-
3.9 - support for reserved words mappings in variable names
-
3.8 - non complex lists were not being compared in equals or hash functions correctly
-
3.7 - resolved an issue with inline enums - thanks to Robert of https://github.com/BlackBeltTechnology
-
3.5 - resolved an issue where class level variables were being duplicated from the parent, causing equals to fail
-
3.4 - backed out some experimental features and exposed the serialization capabilities. fixed a NPE on the copyWith.
-
3.3 - introduces feedback from Jpi & Brian Janssen around making all the LocalApi serializer calls static, so
toJson()
can be called by jsonEncode without introducing non-Dart-like complexity. Further, we introduce an experimental vendor extension on an operation calledx-dart-rich-operationId
- this has to be another operation id, not the same asoperationId:
as Dart cannot have two functions with different return types. It will give you the same method signature, but return the deserialized object, the headers and the status code. It does not interfere with the existing code generation and was introduced to allow situations where session data is being returned outside of the body. It will be documented further once accepted. -
3.2 - introduces support for extra elements in the pubspec, import support, arbitrary part support and a fix for arrays of date times and dates
-
3.1 - introduces support for the Kubernetes API in terms of compilation along with a considerable degree of support for the complexity of that API. It also reduces the code generated when no forms are used or forms are used but not json. It also supports the return of non-json data by just returning the string, allowing you to decode it.
-
2.9 - support inheritance using allOf where it exists. If the model from the generator provides a parentClass we modify the output to now support the correct code generation to support inheritance. Resolve issue around headers not being merged if passed by user. Fix issue with form data generation where fields need to be json encoded.
-
2.8 - resolves a number of Dart Analysis issues
-
2.6/7 - add in a new copyWith() method that allows you to make deep copies of the model and replace specific parts
-
2.5 - fixed a dangling } issue from pedantic, fixed additionalProperties support for k8s api generation, added integration tests
-
2.4 - fixed an issue if no authNames were being provided, a List<dynamic> was created instead of a List<String>
-
2.3 - this is a cleanup of the move to Dio based on pedantic feedback
-
1.5 - fixed the pubspec.yaml
-
1.4 - added in serialization of outgoing data because Dart cannot serialize an enum using json.
-
We intend to support the
oneOf
syntax for parameters for request and response types by using optional parameters. This won’t change method calls when you are only passing one type. -
We will start investigating how to support
anyOf
syntax. -
We will wrap exceptions that have generated models
-
We intend to be generating server side code for supporting Dart server side applications.
To use it, do something like this:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.0.0</version>
<dependencies>
<dependency>
<groupId>com.bluetrainsoftware.maven</groupId>
<artifactId>openapi-dart-generator</artifactId>
<version>4.2</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>mr-api</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<output>${project.basedir}</output>
<inputSpec>${project.basedir}/target/mrapi/mr-api.yaml</inputSpec>
<generatorName>dart2-api</generatorName>
<enablePostProcessFile>true</enablePostProcessFile>
</configuration>
</execution>
</executions>
</plugin>
We use the enablePostProcessFile because if it finds a FLUTTER environment variable, it will run dartfmt on the generated files.
In Gradle, you have to make this extra library available to the buildscript, so at the top of your file before your plugin declaration you need a section similar to:
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "com.bluetrainsoftware.maven:openapi-dart-generator:4.2"
}
}
from there in your openApiGenerator definitions, you specify the server format in additional properties:
openApiGenerate {
generatorName = "dart2-api"
inputSpec = openApiSpec
outputDir = openApiOutputDir
apiPackage = "com.your-company.api"
modelPackage = "com.your-company.api.model"
additionalProperties = [
'key': 'value'
]
configOptions = [:]
}
Please refer to Irina’s article on Medium.
Additional properties allow you to customise how code is generated and we honour 2 of them above the normal ones.
-
pubspec-dependencies
: anything in this will be split on a command added to the dependencies section of your generated code. -
pubspec-dev-dependencies
: anything here will be added to the dev dependencies of your generated code.
the normal ones include:
name: {{pubName}} version: {{pubVersion}} description: {{pubDescription}}
They are specified in the configuration above (Maven example here):
<configuration>
<output>${project.basedir}</output>
<inputSpec>${project.basedir}/target/mrapi/mr-api.yaml</inputSpec>
<generatorName>dart2-api</generatorName>
<enablePostProcessFile>true</enablePostProcessFile>
<additionalProperties>
<additionalProperty>pubName=myapi</additionalProperty>
</additionalProperties>
</configuration>
See the src/it
project for more examples.
You may need to use additional files - just add them to the project or add them via a dependency. You can use the
importMappings
section of the configuration to bring in any packages (internal or external) into the library
definition. For example
<typeMappings>int-or-string=IntOrString</typeMappings>
<importMappings>IntOrString=./int_or_string.dart</importMappings>
This will note anything that has format: int-or-string
and map this to the class IntOrString and there will be an
extra part
import for it added to the library main. You must write this class to have the expected criteria from
the rest of the library but it does allow you to support custom types. Again, an example of this is in src/it
.
If you use something like this instead:
<typeMappings>int-or-string=IntOrString</typeMappings>
<importMappings>IntOrString=package:k8s-dart/int_or_string.dart</importMappings>
Then it will add it to the import
section of your library allowing
you to use external libraries.
We typically use the Dependency Plugin to copy the actual OpenAPI yaml file from a different project - such as in this case "mr-api".
Note
|
you can also customise this using my MergeYaml plugin if you wish to merge apis together. If often do this for testing purposes. |
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack todo api</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>io.yourapi.mr</groupId>
<artifactId>mr-api</artifactId>
<version>1.1-SNAPSHOT</version>
<type>jar</type>
<outputDirectory>${project.basedir}/target/mrapi/</outputDirectory>
</artifactItem>
</artifactItems>
<includes>
**/*.yaml
</includes>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
And we include a custom Clean plugin definition to ensure old artifacts aren’t left behind as you generate.
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<filesets>
<fileset>
<directory>lib</directory>
<includes>
<include>**/**</include>
</includes>
</fileset>
<fileset>
<directory>docs</directory>
<includes>
<include>**/**</include>
</includes>
</fileset>
<fileset>
<directory>test</directory>
<includes>
<include>**/**</include>
</includes>
</fileset>
<fileset>
<directory>.openapi-generator</directory>
<includes>
<include>**/**</include>
</includes>
</fileset>
<fileset>
<directory>.openapi-generator</directory>
<includes>
<include>**/**</include>
</includes>
</fileset>
</filesets>
</configuration>
</plugin>