跳到主要内容

扩展

引言

Ent 的 扩展 API 有助于创建代码生成扩展,这些扩展将代码生成钩子模板注解捆绑在一起,以创建可重用的组件, 为 Ent 核心添加新的丰富功能。例如,Ent 的 entgql 插件 暴露了一个 Extension,可以从 Ent 模式自动生成 GraphQL 服务器。

定义新扩展

所有扩展都必须实现 Extension 接口:

type Extension interface {
// Hooks 包含一系列在代码生成前后应用于图的可选钩子
Hooks() []gen.Hook

// Annotations 向 gen.Config 对象注入全局注解,
// 这些注解可以在所有模板中全局访问。与模式注解不同,
// 不需要强制可序列化为 JSON 原始值。
//
// {{- with $.Config.Annotations.GQL }}
// {{/* 注解用法在此处 */}}
// {{- end }}
//
Annotations() []Annotation

// Templates 指定要执行或覆盖默认模板的
// 替代模板列表。
Templates() []*gen.Template

// Options 指定在执行代码生成之前要在 gen.Config 上
// 评估的 entc.Options 列表。
Options() []Option
}

为了简化新扩展的开发,开发者可以嵌入 entc.DefaultExtension 来创建扩展,而无需实现所有方法:

package hello

// GreetExtension 实现 entc.Extension。
type GreetExtension struct {
entc.DefaultExtension
}

添加模板

Ent 支持添加在代码生成期间渲染的外部模板。要在扩展上捆绑此类外部模板,请实现 Templates 方法:

templates/greet.tmpl
{{/* 告诉 Intellij/GoLand 启用基于 *gen.Graph 类型的自动补全。 */}}
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}

{{ define "greet" }}

{{/* 为生成的文件添加基础头部 */}}
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}

{{/* 循环所有节点并添加 Greet 方法 */}}
{{ range $n := $.Nodes }}
{{ $receiver := $n.Receiver }}
func ({{ $receiver }} *{{ $n.Name }}) Greet() string {
return "Hello, {{ $n.Name }}"
}
{{ end }}

{{ end }}
func (*GreetExtension) Templates() []*gen.Template {
return []*gen.Template{
gen.MustParse(gen.NewTemplate("greet").ParseFiles("templates/greet.tmpl")),
}
}

添加全局注解

注解是一种方便的方式,为扩展的用户提供 API 来修改代码生成的行为。要向我们的扩展添加注解, 请实现 Annotations 方法。假设在我们的 GreetExtension 中,我们想 为用户提供配置生成代码中问候词语的能力:

// GreetingWord 实现 entc.Annotation。
type GreetingWord string

// 注解的名称。由代码生成模板使用。
func (GreetingWord) Name() string {
return "GreetingWord"
}

然后将其添加到 GreetExtension 结构体中:

type GreetExtension struct {
entc.DefaultExtension
word GreetingWord
}

接下来,实现 Annotations 方法:

func (s *GreetExtension) Annotations() []entc.Annotation {
return []entc.Annotation{
s.word,
}
}

现在,从您的模板中可以访问 GreetingWord 注解:

func ({{ $receiver }} *{{ $n.Name }}) Greet() string {
return "{{ $.Annotations.GreetingWord }}, {{ $n.Name }}"
}

添加钩子

entc 包提供了一个选项,用于向代码生成阶段添加一系列钩子 (中间件)。此选项非常适合为模式添加自定义验证器,或使用图模式生成其他资产。要将 代码生成钩子与您的扩展捆绑,请实现 Hooks 方法:

func (s *GreetExtension) Hooks() []gen.Hook {
return []gen.Hook{
DisallowTypeName("Shalom"),
}
}

// DisallowTypeName 确保图中没有具有给定名称的 ent.Schema。
func DisallowTypeName(name string) gen.Hook {
return func(next gen.Generator) gen.Generator {
return gen.GenerateFunc(func(g *gen.Graph) error {
for _, node := range g.Nodes {
if node.Name == name {
return fmt.Errorf("entc: validation failed, type named %q not allowed", name)
}
}
return next.Generate(g)
})
}
}

在代码生成中使用扩展

要在我们的代码生成配置中使用扩展,请使用 entc.Extensions,这是一个辅助 方法,返回应用我们选择的扩展的 entc.Option

ent/entc.go
//+build ignore

package main

import (
"fmt"
"log"

"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)

func main() {
err := entc.Generate("./schema",
&gen.Config{},
entc.Extensions(&GreetExtension{
word: GreetingWord("Shalom"),
}),
)
if err != nil {
log.Fatal("running ent codegen:", err)
}
}

社区扩展

  • entoas entoas 是一个源自 elk 的扩展,已移植为自己的扩展,现在是官方 生成器,用于生成固执己见的 OpenAPI 规范文档。您可以使用它快速开发和记录 RESTful HTTP 服务器。很快将发布一个新的扩展,提供一个使用 ent 集成 entoas 提供的文档的生成实现。

  • entrest entrestentoas(+ ogent)和 elk(在其停产之前)的替代方案。entrest 从您的 Ent 模式生成符合规范、 高效且功能完整的 OpenAPI 规范,以及功能性的 RESTful API 服务器实现。其亮点功能包括:可切换的分页、 高级过滤/查询功能、排序(甚至通过关系)、预先加载边,以及更多功能。

  • entgql 此扩展帮助用户从 Ent 模式构建 GraphQL 服务器。entgqlgqlgen 集成,这是一个流行的、模式优先的 Go 库,用于构建 GraphQL 服务器。 该扩展包括生成类型安全的 GraphQL 过滤器,使用户能够轻松地将 GraphQL 查询映射到 Ent 查询。 遵循本教程开始使用。

  • entproto entproto 从 Ent 模式生成 Protobuf 消息定义和 gRPC 服务定义。该项目还包括 protoc-gen-entgrpc,一个 protoc(Protobuf 编译器)插件,用于生成由 Entproto 生成的 gRPC 服务定义的 工作实现。通过这种方式,我们可以轻松创建一个 gRPC 服务器,无需编写任何代码(除了定义 Ent 模式外)即可服务于 我们的服务请求! 要了解如何使用和设置 entproto,请阅读本教程。更多背景信息, 您可以阅读这篇博文, 或这篇博文讨论更多 entproto 功能。

  • elk (已停产) elk 是一个从 Ent 模式生成 RESTful API 端点的扩展。该扩展从 Ent 模式生成 HTTP CRUD 处理程序,以及一个 OpenAPI JSON 文件。通过使用它,您可以轻松为您的应用程序构建 RESTful HTTP 服务器。 请注意,elk 已停产,转而支持 entoas。一个实现生成器正在开发中。 阅读这篇博文了解如何 使用 elk,以及这篇博文了解如何生成 OpenAPI 规范

  • entviz (已停产) entviz 是一个从 Ent 模式生成可视化图表的扩展。这些图表在 Web 浏览器中可视化模式, 并随着我们继续编码而保持更新。entviz 可以配置为每次我们重新生成模式时自动更新图表, 从而便于查看所做的更改。 在这篇博文中学习如何 在您的项目中集成 entviz此扩展已于 2023-09-16 由维护者存档