A few months ago, Ariel made a silent but highly-impactful contribution to Ent's core, the Extension API. While Ent has had extension capabilities (such as Code-gen Hooks, External Templates, and Annotations) for a long time, there wasn't a convenient way to bundle together all of these moving parts into a coherent, self-contained component. The Extension API which we discuss in the post does exactly that.
Many open-source ecosystems thrive specifically because they excel at providing developers an
easy and structured way to extend a small, core system. Much criticism has been made of the
Node.js ecosystem (even by its original creator Ryan Dahl)
but it is very hard to argue that the ease of publishing and consuming new
facilitated the explosion in its popularity. I've discussed on my personal blog how
protoc's plugin system works
and how that made the Protobuf ecosystem thrive. In short, ecosystems are only created under
In our post today, we will explore Ent's
Extension API by building a toy example.
The Extension API only works for projects use Ent's code-generation as a Go package.
To set that up, after initializing your project, create a new file named
ent/generate.go to invoke our
All extension's must implement the Extension interface:
To simplify the development of new extensions, developers can embed entc.DefaultExtension
to create extensions without implementing all methods. In
Currently, our extension doesn't do anything. Next, let's connect it to our code-generation config.
entc.go, add our new extension to the
External templates can be bundled into extensions to enhance Ent's core code-generation
functionality. With our toy example, our goal is to add to each entity a generated method
Greet that returns a greeting with the type's name when invoked. We're aiming for something
To do this, let's add a new external template file and place it in
Next, let's implement the
Next, let's kick the tires on our extension. Add a new schema for the
User type in a file
Observe that a new file,
ent/greet.go, was created, it contains:
Great! Our extension was invoked from Ent's code-generation and produced the code we wanted for our schema!
Annotations provide a way to supply users of our extension with an API
to modify the behavior of code generation logic. To add annotations to our extension,
Annotations method. Suppose that for our
GreetExtension we want
to provide users with the ability to configure the greeting word in the generated
Next, we add a
word field to our
Next, implement the
Now, from within your templates you can access the
GreetingWord annotation. Modify
ent/templates/greet.tmpl to use our new annotation:
Next, modify the code-generation configuration to set the GreetingWord annotation:
To see our annotation control the generated code, re-run:
Finally, observe that the generated
ent/greet.go was updated:
Hooray! We added an option to use an annotation to control the greeting word in the
In addition to templates and annotations, the Extension API allows developers to bundle
entc.Options in extensions to further control the behavior of your code-generation.
In this post we will not discuss these possibilities, but if you are interested in using them
head over to the documentation.
In this post we explored via a toy example how to use the
Extension API to create new
Ent code-generation extensions. As we've mentioned above, modular design that allows anyone
to extend the core functionality of software is critical to the success of any ecosystem.
We're seeing this claim start to realize with the Ent community, here's a list of some
interesting projects that use the Extension API:
- elk - an extension to generate REST endpoints from Ent schemas.
- entgql - generate GraphQL servers from Ent schemas.
- entviz - generate ER diagrams from Ent schemas.
And what about you? Do you have an idea for a useful Ent extension? I hope this post demonstrated that with the new Extension API, it is not a difficult task.
Have questions? Need help with getting started? Feel free to join our Slack channel.