Skip to content

Codegen Configuration

entrest.Config is passed to entrest.NewExtension in your entc.go file. It runs at code generation time and controls what paths, parameters, and schemas appear in openapi.json.

internal/database/entc.go
//go:build ignore
// Copyright (c) Liam Stanley <liam@liam.sh>. All rights reserved. Use of
// this source code is governed by the MIT license that can be found in
// the LICENSE file.
package main
import (
"log"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
"github.com/lrstanley/entrest"
)
func main() {
ex, err := entrest.NewExtension(&entrest.Config{
SpecFromPath: "../base-openapi.json", // Using a base spec to start with, not required.
Handler: entrest.HandlerStdlib,
WithTesting: true,
StrictMutate: true,
ListNotFound: true,
DefaultFilterID: true,
GlobalRequestHeaders: entrest.RequestIDHeader,
GlobalResponseHeaders: entrest.RateLimitHeaders,
})
if err != nil {
log.Fatalf("creating entrest extension: %v", err)
}
err = entc.Generate(
"./database/schema",
&gen.Config{
Target: "./database/ent",
Schema: "github.com/example/my-project/internal/database/schema",
Package: "github.com/example/my-project/internal/database/ent",
Features: []gen.Feature{
gen.FeaturePrivacy,
},
},
entc.Extensions(ex),
)
if err != nil {
log.Fatalf("failed to run ent codegen: %v", err)
}
}

NewExtension(nil) is equivalent to NewExtension(&entrest.Config{}). Most fields have defaults applied in Validate before generation runs.

If you do not provide Spec or SpecFromPath, entrest starts from an empty spec and sets:

FieldDefault
openapi3.0.3
info.titleEntGo Rest API
info.version1.0.0

Set API title, description, servers, security schemes, and custom paths through Extending the Spec.

DefaultOperations lists which CRUD operations are generated for every schema by default. When unset, all five are enabled: create, read, update, delete, and list.

Per-schema or per-edge overrides use WithIncludeOperations and WithExcludeOperations.

Read-only API (list and get only):

internal/database/entc.go
ex, err := entrest.NewExtension(&entrest.Config{
DefaultOperations: []entrest.Operation{
entrest.OperationList,
entrest.OperationRead,
},
})

An empty DefaultOperations list fails validation — at least one operation is required.

DefaultFilterID adds id filter parameters to list endpoints when your schema does not declare an explicit id field (ent's implicit ID). The filters use the EQ and array predicate groups. Edge list filters are not added unless the edge is marked filterable with WithFilter.

List endpoints are paginated by default. Global defaults:

OptionDefault
ItemsPerPage10
MinItemsPerPage1
MaxItemsPerPage100

DisablePagination turns pagination off globally; per-schema overrides use WithPagination.

See Pagination for query parameters, response shape, and per-schema limits.

OptionDefaultPurpose
DefaultEagerLoadfalseEager-load every edge
EagerLoadLimit1000Max items per eager-loaded edge (-1 disables)
DisableEagerLoadNonPagedOptfalseKeep pagination on eager-loaded edge endpoints
DisableEagerLoadedEndpointsfalseSkip edge endpoints when the edge is eager-loaded
DisableEdgeEndpointsfalseSkip all edge endpoints

Per-edge behavior is controlled with annotations such as WithEagerLoad and WithEdgeEndpoint.

See Eager Loading for usage and when not to eager-load.

AddEdgesToTags adds eager-loaded edge entity names to the tags array on parent schema operations. Edge endpoints already include both parent and child tags. This is mainly useful for large schemas where tags help clients find related resources in the spec.

StrictMutate documents and enforces 400 responses when create or update bodies contain fields not defined on the schema.

ListNotFound documents 404 on list endpoints when filters match no rows. The default is 200 with an empty content array. See Error handling for the response shape.

AllowClientIDs allows an id field in create request bodies (for client-supplied UUIDs or natural keys). This is a security sensitive option — see Auth and permissions. Per-schema control uses WithAllowClientIDs.

DisablePatchJSONTag skips entrest's JSON tag hook that removes omitempty from generated struct tags. With the hook enabled (default), optional and defaulted fields still appear in JSON responses. Fields marked json:"-" are unchanged.

Global request headers, response headers, and error response schemas are configured on GlobalRequestHeaders, GlobalResponseHeaders, and GlobalErrorResponses. When unset, error responses default to DefaultErrorResponses (400, 401, 403, 404, 409, 429, 500).

See Extending the Spec for presets (RequestIDHeader, RateLimitHeaders), custom headers, and hooks.

OptionEffect on the spec
HandlerHandlerNone generates only openapi.json — no rest handler package. HandlerStdlib or HandlerChi also generate handler code. See Mount the Handler.
DisableSpecHandlerOmits GET /openapi.json from the spec, disables embedding the spec in the binary, and turns off /docs and Link header support in the handler.
WriterWrite the spec to a custom io.Writer instead of <ent>/rest/openapi.json.
TemplatesAdditional or replacement gen.Template values for handler codegen.

WithTesting generates resttest helpers; it requires a non-HandlerNone handler. See Testing.

When handler generation is enabled and the spec handler is not disabled, the embedded spec is served at GET {BasePath}/openapi.json. See API Docs.

PreGenerateHook runs before paths are merged into the base spec. PostGenerateHook runs after merge but before global headers and error responses are applied — use it when custom paths should receive those globals. PreWriteHook runs after the full spec is resolved, immediately before it is written.

Examples are in Extending the Spec.

Most global options have matching annotations on schemas, edges, or fields. The full list is on Annotation Reference.

llms.txtdocumentation for LLMs