This article explores the Mustache templates, in the context of the OpenAPI specification, and the underrated features that can help developers in optimizing the code generation.
At Adyen we adopted OpenAPI specs some time ago and we have created our own Mustache templates to streamline the generation of the Adyen SDKs (in various languages) every time there is a new release of the payment APIs.
Mustache is a logic-less template framework used to generate output that must conform to a structure and format we want to control. The applications are several: generating code, HTML, configuration files, etc…
They are logic-less (meaning the actual templating engine must take care of the conversion logic), simple (having just the features you need — no-frills) and open-source.
In a nutshell
Given a template
Hello {{name}} {{lastname}}
and a data structure
{
"name": "Beppe",
"lastname": "Catanese"
}
the template engine will know how to produce.
Hello Beppe Catanese
OpenAPI language templates
The OpenAPI Generator project allows the generation of (client, server and models) code starting from a valid OpenAPI specification, either json
or yaml
. This is an extremely valuable feature for API-driven products where code and API specs change often and need to keep aligned (at ideally small effort).
In this workflow Mustache templates play a key role: for each language and framework OpenAPI provides a default implementation (based on predefined Mustache templates) which works really well in most cases and can be tuned further (extending the templates) when needed.
Becoming a Mustache master
Let’s dive into the more advanced features that make Mustache templates really powerful.
Parameters list
Use ^last
to add the comma between parameters unless it is the last one
{{#allParams}}paramName *{{{dataType}}}{{^last}}, {{/last}}{{/allParams}}
-> user *string, address *string, nationality *string
Naming parameters with a sequence
Use -index to access the index while traversing an array or list
{{#allParams}}req{{-index}} *{{{dataType}}}{{^last}}, {{/last}}{{/allParams}}
-> req1 *string, req2 *string, req3 *string
Distinguish between parameters
While allParams
gives access to the whole list of parameters, it is useful to make a distinction when generating method signatures or documentation
{{#pathParams}}...{{/pathParams}}
{{#bodyParams}}...{{/bodyParams}}
{{#queryParams}}...{{/queryParams}}
Comments
Comments are useful in templates too, but rarely seen
/**
Info about the method
{{! comments to be ignore when parsing the template}}
**/
Custom delimiter
The default delimiters {{
and }}
can be overridden (some scripting languages use brace brackets)
{{! change delimiters to <% and %>}}
{{=<% %>=}}
First and last element
While traversing arrays it is useful to access easily the first and the last element, for example the Go imports group all modules in a list starting and finishing with parenthesis
{{#-first}}
import (
{{/-first}}
"{{import}}"
{{#-last}}
)
{{/-last}}
-> import (
"fmt"
"math"
)
Lamba functions
There is a small set of functions available during the OpenAPI codegen phase: those are convenient when you need to lowercase a package name or camelCase a method.
lowercase(Beppe) -> beppe
uppercase(Beppe) -> BEPPE
titlecase(Beppe likes mustache) -> Beppe Likes Mustache
camelcase(Beppe-Catanese) -> BeppeCatanese
indented -> add indentation
Create custom generator
When specific customisation is necessary OpenAPI codegen allows to extend the specific-language generator to add (or redefine) the generation logic. The approach by extension is pretty straight-forward:
1: extend the client code generator (for example implementing the renaming of the operationId attribute)
2: generate the code using the new generator
See my gist MyGoClientCodegen
Generate the client code using the new CodeGen implementation
java -jar openapi-generator-cli.jar generate \
-i /openapi.yaml -t templates/go -g go \
-p packageName=Checkout -o src/checkout \
-g org.mycompany.codegen.MyGoClientCodegen
Conclusion
Check out our Go Library to see the customisation of the Mustache templates and how the code generation is performed starting from the Adyen OpenAPI specs. And get ready for more articles and insights around our work with OpenAPI (i.e generating server stubs, testing, mocking and validation).
Lateeeeeer!
Top comments (0)