entrest

Codegen Configuration

Generation-time options on entrest.Config that shape the OpenAPI spec.

Reference

Generation-time options on entrest.Config that shape the OpenAPI spec. Runtime handler options live on Runtime 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.

Setup

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.

Default spec metadata

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.

Operations

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.

Filtering

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.

Pagination

List endpoints are paginated by default. Global defaults:

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

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

Eager loading

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.

Tags

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.

Mutation and list responses

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.

JSON response bodies

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.

Headers and error responses

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.

Handler generation and spec output

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.

Hooks

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.

Per-schema overrides

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

Last updated on

On this page