Saltar al contenido principal

Presentamos "entoas": una extensión para generar automáticamente documentos de especificación OpenAPI desde esquemas Ent

· 6 min de lectura
[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

La Especificación OpenAPI (OAS, anteriormente conocida como Swagger Specification) es un estándar técnico que define una descripción de interfaz independiente del lenguaje para APIs REST. Esto permite tanto a humanos como a herramientas automatizadas entender el servicio descrito sin necesidad de acceder al código fuente o documentación adicional. Combinada con las herramientas Swagger, puedes generar código boilerplate para servidores y clientes en más de 20 lenguajes simplemente proporcionando el documento OAS.

En un blog anterior, os presentamos una nueva característica de la extensión elk de Ent: un generador de documentos OpenAPI Specification completamente compatible.

Hoy nos complace anunciar que el generador de especificaciones se ha convertido en una extensión oficial del proyecto Ent y ha sido trasladado al repositorio ent/contrib. Además, hemos escuchado los comentarios de la comunidad e implementado mejoras que esperamos os gusten.

Empezando

Para usar la extensión entoas, utiliza el paquete entc (ent codegen) como se describe aquí. Primero instala la extensión en tu módulo Go:

go get entgo.io/contrib/entoas

Ahora sigue estos dos pasos para activarla y configurar Ent para trabajar con la extensión entoas:

1. Crea un nuevo archivo Go llamado ent/entc.go y pega el siguiente contenido:

// +build ignore

package main

import (
"log"

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

func main() {
ex, err := entoas.NewExtension()
if err != nil {
log.Fatalf("creating entoas extension: %v", err)
}
err = entc.Generate("./schema", &gen.Config{}, entc.Extensions(ex))
if err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}

2. Edita el archivo ent/generate.go para ejecutar el archivo ent/entc.go:

package ent

//go:generate go run -mod=mod entc.go

¡Con estos pasos completados, todo está listo para generar documentos OAS desde tus esquemas! Si eres nuevo en Ent y quieres aprender más sobre cómo conectar diferentes tipos de bases de datos, ejecutar migraciones o trabajar con entidades, visita el Tutorial de Configuración.

Generar un documento OAS

El primer paso para crear nuestro documento OAS es definir un grafo de esquemas Ent. Para brevedad, aquí tienes un esquema de ejemplo:

ent/schema/schema.go
package schema

import (
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)

// Fridge holds the schema definition for the Fridge entity.
type Fridge struct {
ent.Schema
}

// Fields of the Fridge.
func (Fridge) Fields() []ent.Field {
return []ent.Field{
field.String("title"),
}
}

// Edges of the Fridge.
func (Fridge) Edges() []ent.Edge {
return []ent.Edge{
edge.To("compartments", Compartment.Type),
}
}

// Compartment holds the schema definition for the Compartment entity.
type Compartment struct {
ent.Schema
}

// Fields of the Compartment.
func (Compartment) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
}
}

// Edges of the Compartment.
func (Compartment) Edges() []ent.Edge {
return []ent.Edge{
edge.From("fridge", Fridge.Type).
Ref("compartments").
Unique(),
edge.To("contents", Item.Type),
}
}

// Item holds the schema definition for the Item entity.
type Item struct {
ent.Schema
}

// Fields of the Item.
func (Item) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
}
}

// Edges of the Item.
func (Item) Edges() []ent.Edge {
return []ent.Edge{
edge.From("compartment", Compartment.Type).
Ref("contents").
Unique(),
}
}

El código anterior muestra la forma característica de Ent para describir un grafo de esquemas. En este caso creamos tres entidades: Fridge, Compartment e Item. Además, añadimos relaciones: una nevera puede tener varios compartimentos, y un compartimento puede contener varios items.

Ahora ejecuta el generador de código:

go generate ./...

Además de los archivos que Ent genera normalmente, se creará un nuevo archivo llamado ent/openapi.json. Aquí tienes un avance de su contenido:

ent/openapi.json
{
"info": {
"title": "Ent Schema API",
"description": "This is an auto generated API description made out of an Ent schema definition",
"termsOfService": "",
"contact": {},
"license": {
"name": ""
},
"version": "0.0.0"
},
"paths": {
"/compartments": {
"get": {
[...]

Si lo deseas, copia su contenido y pégualo en el Swagger Editor. Debería verse así:

Swagger Editor

Swagger Editor

Configuración básica

La descripción de nuestra API aún no refleja su funcionalidad, ¡pero entoas permite personalizarlo! Abre ent/entc.go y actualiza el título y descripción de nuestra API de neveras:

ent/entc.go
//go:build ignore
// +build ignore

package main

import (
"log"

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

func main() {
ex, err := entoas.NewExtension(
entoas.SpecTitle("Fridge CMS"),
entoas.SpecDescription("API to manage fridges and their cooled contents. **ICY!**"),
entoas.SpecVersion("0.0.1"),
)
if err != nil {
log.Fatalf("creating entoas extension: %v", err)
}
err = entc.Generate("./schema", &gen.Config{}, entc.Extensions(ex))
if err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}

Al regenerar el código se creará un documento OAS actualizado.

ent/openapi.json
{
"info": {
"title": "Fridge CMS",
"description": "API to manage fridges and their cooled contents. **ICY!**",
"termsOfService": "",
"contact": {},
"license": {
"name": ""
},
"version": "0.0.1"
},
"paths": {
"/compartments": {
"get": {
[...]

Configuración de operaciones

A veces no querrás generar endpoints para todas las operaciones de cada nodo. Afortunadamente, entoas permite configurar qué endpoints generar y cuáles ignorar. La política predeterminada de entoas es exponer todas las rutas. Puedes cambiar este comportamiento para no exponer ninguna ruta excepto las solicitadas explícitamente, o simplemente indicar a entoas que excluya operaciones específicas usando entoas.Annotation. Las políticas también controlan operaciones de sub-recursos:

ent/schema/fridge.go
// Edges of the Fridge.
func (Fridge) Edges() []ent.Edge {
return []ent.Edge{
edge.To("compartments", Compartment.Type).
// Do not generate an endpoint for POST /fridges/{id}/compartments
Annotations(
entoas.CreateOperation(
entoas.OperationPolicy(entoas.PolicyExclude),
),
),
}
}

// Annotations of the Fridge.
func (Fridge) Annotations() []schema.Annotation {
return []schema.Annotation{
// Do not generate an endpoint for DELETE /fridges/{id}
entoas.DeleteOperation(entoas.OperationPolicy(entoas.PolicyExclude)),
}
}

¡Y voilà! Las operaciones han desaparecido.

Para más detalles sobre el funcionamiento de políticas en entoas y sus posibilidades, consulta la godoc.

Modelos simplificados

Por defecto entoas genera un esquema de respuesta por endpoint. La estrategia de nombres se detalla en la godoc.

One Schema per Endpoint

One Schema per Endpoint

Muchos usuarios solicitaron cambiar este comportamiento para mapear directamente los esquemas Ent al documento OAS. Ahora puedes configurar entoas para lograrlo:

ex, err := entoas.NewExtension(
entoas.SpecTitle("Fridge CMS"),
entoas.SpecDescription("API to manage fridges and their cooled contents. **ICY!**"),
entoas.SpecVersion("0.0.1"),
entoas.SimpleModels(),
)
Simple Schemas

Simple Schemas

Conclusión

En este anuncio presentamos entoas, la integración oficial en Ent del generador de especificaciones OpenAPI que antes formaba parte de elk. Esta característica conecta las capacidades de generación de código de Ent con el rico ecosistema de herramientas OpenAPI/Swagger.

¿Tienes preguntas? ¿Necesitas ayuda para empezar? Únete a nuestro servidor de Discord o canal de Slack.

[Para más noticias y actualizaciones de Ent:]