Upgrade your swagger generated angular project to Angular 7/8

Douglas Liu
Sohoffice
Published in
4 min readDec 13, 2018

I have a project that ran on angular 6, the API access layer was generated by swagger-codegen. This is actually a very good practice where you don’t have to repeat the JS / TS service that calls remote API or those transfer objects that are required to use these API.

Until I realize the angular production build of version 6 is super slow.

Photo by Sam Mgrdichian on Unsplash

The ng build --prod --aot took a very long time to stop at 92% chunk asset optimization. After reading up this thread, I decided this is a good time to upgrade to angular 7.

All steps described in this article also work with Angular 8. Swagger codegen v3 is still broken, 2.4.x is still the closest version that seems to be working, and 2.4.5 is the latest version on docker. — Jun 5th 2019

The angular upgrade itself is not a problem, just follow the instructions and you’ll be fine. This is especially true if you’re coming from angular 6. Make sure you also upgrade the other dependencies and remove rxjs-compat (you should not be needed it). I found this post very helpful to myself.

The problem, however, is swagger-codegen.

Related on #Angular #Swagger

swagger-codegen 2.3.1

I was originally running swagger-codegen 2.3.1 and use language typescript-angular. After upgrading to angular 7, the same services gave me the below.

ERROR in node_modules/rxjs/Observable.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Observable'....

The problem is the import path. import { Observable } from 'rxjs/Observable' is no longer correct. If I manually fix the import path to import {Observable} from 'rxjs' the application will stop complaining.

I had upgraded my swagger-codegen options to 7.1.3, but it didn’t help.

# swagger-codegen.options
{
"ngVersion": "7.1.3"
}
# Generate command through docker
docker
run --rm --net=host -u="$(id -u)" -v ${PWD}:/local swaggerapi/swagger-codegen-cli:v2.3.1 generate \
-Dio.swagger.parser.util.RemoteUrl.trustAll=true \
-i https://localhost:19000/docs/spec \
-l typescript-angular \
-o /local/src/app \
-c /local/bin/swagger-codegen.options

Obviously we’ll need to upgrade swagger-codegen as well.

swagger-codegen 3.0.3

v3.0.3 doesn’t have docker release (yet). So I’ll have to use brew to install it. The latest version I can find so far is 3.0.3.

v3.0.3 failed pathetically for not connecting to sites with self signed certificate, even if you use the recommended option.

swagger-codegen generate \
-Dio.swagger.parser.util.RemoteUrl.trustAll=true \
-i https://localhost:19000/docs/spec \
-l typescript-angular \
-o "$BASEDIR/src/app" \
-c "$BASEDIR/bin/swagger-codegen.options"
# Failed
[main] ERROR io.swagger.parser.util.RemoteUrl - unable to read
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I tried to get around it by downloading the spec with wget.

mkdir -p tmp
SPECFILE=tmp/some-spec.json
wget --quiet --no-check-certificate https://localhost:19000/docs/spec -O $SPECFILE

swagger-codegen generate \
-Dio.swagger.parser.util.RemoteUrl.trustAll=true \
-i $SPECFILE \
-l typescript-angular \
-o "$BASEDIR/src/app" \
-c "$BASEDIR/bin/swagger-codegen.options"

retval=$?
if [ $retval -ne 0 ]; then
echo "Swagger codegen error" >&2
exit
1
fi

# Delete the downloaded spec file.
rm $SPECFILE

It did generate, but unfortunately with much more errors than v2.3.1. And the rxjs import path weren’t fixed.

ERROR in src/app/api/someAsset.service.ts(169,1): error TS1005: '}' expected....ERROR in node_modules/rxjs/Observable.d.ts(1,15): error TS2307: Cannot find module 'rxjs-compat/Observable'.

There’s a version v2.4.0 in between v3 and v2.3.1. I guess I’ll have to give it a try.

swagger-codegen 2.4.0

swagger-codegen generates fewer errors (yeah!), so I decided to use this.

docker run --rm --net=host -u="$(id -u)" -v ${PWD}:/local swaggerapi/swagger-codegen-cli:2.4.0 generate \
-Dio.swagger.parser.util.RemoteUrl.trustAll=true \
-i https://localhost:19000/docs/spec \
-l typescript-angular \
-o /local/src/app \
-c /local/bin/swagger-codegen.options
# ng serve errorsERROR in src/app/api/foo.service.ts(241,26): error TS1345: An expression of type 'void' cannot be tested for truthiness

The service in question looks like this.

let formParams: { append(param: string, value: any): void; }; ...if (file !== undefined) {    # This is line 241
formParams = formParams.append('file', <any>file) || formParams;
}

Obviously the line 241 tried to assign the return value of append() back to formParams, but the return type is void. So the typescript compiler complains about it.

Simply change the return type to any will silent the compiler. But we need to automate it.

# postprocess scriptif [ -f "$1" ]; then
FN=$(basename $1)
echo
Working on $1.

cp "$1" "/tmp/$FN"
sed -E 's/(formParams.*append\([^,]*: *string,[^,]*: *any\)): void/\1: any/' "/tmp/$FN" > "$1"
rm
"/tmp/$FN"
else
echo $1 is not a file.
fi

This is basically a sed script that replace the return type to any. We can call it with find, right after you generated the code.

docker run --rm --net=host -u="$(id -u)" -v ${PWD}:/local swaggerapi/swagger-codegen-cli:2.4.0 generate \
...
find "$BASEDIR/src/app/api" -name '*.ts' -print -exec "$DIR/swagger-codegen-postprocess.sh" {} ";"

That should fix all the problems (so far).

Conclusion

If you’re using swagger-codegen to generate your API access layer. Use v2.4.0 and update the return type of formParams.append() to any.

If you would like to try edge version, which according to developer should have all the issues fixed. Use wget to download spec and feed it to swagger-codegen as it doesn’t work with self signed certificates (yet).

More on #Swagger

Did you learn something new? If so please:

clap 👏 button below️ so more people can see this

--

--

Douglas Liu
Sohoffice

Problem solver. Found love in Scala, Java, Angular and more …