Hi! We are using openapi generation for dart files to work with backend. And we experience the following issues:

  • Generator setup for new people is complex
  • We have to download the spec manually
  • The generated code contains import errors
  • The generated code is not formatted properly

In this article you will find out how we resolved the problem and even get a script which resolve all the issues.

Complex setup

Generation requires at least 2 files: a generator jar(or cli installed via npm) and openapi.yaml. You also need to know the syntax of an openapi generator. We don't want that to be the focus of our developers. So I started to write the script which would help with that:

if [ -f "$FILE" ]; then
    echo "$FILE exists."
  echo "openapi-generator-cli-4.3.1.jar file not found, downloading..."
  curl "https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/4.3.1/openapi-generator-cli-4.3.1.jar" --output "$FILE"

java -jar "`pwd`/openapi-generator-cli-4.3.1.jar" generate -i "$BASE_PATH/openapi.yaml" -g dart-dio -o "$BASE_PATH/newversion"

The script checks if the jar file is downloaded and downloads it from maven repo if it is not there. Then the generation itself is launched with the '-o' argument pointing to the output folder.

Errors in generated code.

The generated code uses 'package:openapi' imports inside the generated code. This is wrong. The relative imports should be used instead. There are 3 groups of files which require slight modifications.

  1. Model files
  2. default_api.dart file
  3. serializers.dart file

Model files

Model files are importing other model files. No need to for a package import, we may just import the file itself. Instead of

import 'package:openapi/model/activity.dart';

we should have

import 'activity.dart';

Let's patch it. We need to iterate over the files in the 'model' folder and replace the imports:

for i in $(ls);  
    	sed -e 's/package:openapi\/model\///g' "$GENERATED_MODEL_PATH/$i" >  $TMP && mv $TMP "$BASE_MODEL_PATH/$i"    
    flutter format "$BASE_MODEL_PATH/$i"  

We are not using '-i' option of sed as it is not working on Unix systems and go against it's phylosophy. We also format the file right away.

API file

The default_api also uses the model files but it is placed in api folder. Let's patch it as well:

sed -e 's/package:openapi\/model\//..\/model\//g' "$GENERATED_PATH/api/default_api.dart" >  $TMP && mv $TMP "$BASE_PATH/api/default_api.dart"

Serializers file

The serializers.dart file is placed in the root folder. So are fixing imports for it:

sed -e 's/package:openapi\/model\//model\//g' "$GENERATED_PATH/serializers.dart" >  $TMP && mv $TMP "$BASE_PATH/serializers.dart"

Avoid manual download of openapi specification with Gitlab

We can also avoid downloading the specification manually and automate it as well. We need a personal token and project id of the backend repository our spec is corresponding to. Then we just make a curl request.

Personal Token.

Open your profile:

And choose Access Tokens in the left menu. You will be able to create a new access token. Don't forget to right it down as you will see it only once in Gitlab :)

Project Id.

It is written in the header of the repository:

Now we can make an appropriate call:

curl -XGET --header "PRIVATE-TOKEN: YOUR-TOKEN” "https://gitlab.com/api/v4/projects/$2/repository/files/api%2fopenapi.yaml/raw?ref=master" > "$BASE_PATH/openapi.yaml"

Please, pay attention to url encoding of the file path('/' -> '%2f').

Build_runner & Cleanup

If you are using Dio you need to generate the *.g.dart files as well:

echo "generating build_value..."
flutter pub run build_runner build

Now we can clean the temporary files.

echo "Removing temporary files"
rm -rf ./newversion

Full Script

You can find the full script at my Github. Feel free to patch it and don't forget to Signup for future updates!

P.S. if you don't like this apporach our EPAM folks created a package to do the similiar thing with swagger files, chopper and json_serializable.