fibgen

module
v0.0.0-...-cd2c16d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT

README

fibgen

Generate a complete OpenAPI document (3.1 and 3.0) for Go + Fiber services through static analysis.

No annotations, no // @Summary comments, no code generation, no changes to your handlers. Point fibgen at an existing project and get a spec with paths, parameters, request bodies, per-status responses, and fully resolved type schemas ($ref, enums, nullables).

Supports Fiber v2 and v3.

Go Reference


Why static analysis

Every Fiber handler is just func(c fiber.Ctx) error (v3) or func(c *fiber.Ctx) error (v2). The request and response types exist only as local variables inside the body (c.Bind().Body(&dto), c.JSON(user)). The signature is opaque, so runtime reflection yields nothing useful.

The only way to get "fully automatic, on unmodified code" is to analyze the code itself with go/packages + go/types: find the route registrations, follow them into the handler body, and recover the types from the c.* calls.

Install

go install github.com/nyawave/fibgen/cmd/fibgen@latest

Or build from source:

git clone https://github.com/nyawave/fibgen
cd fibgen
./build.sh           # -> ./bin/fibgen   (build.bat on Windows)

Usage

# from the root of the project you want to document
fibgen ./... > openapi.yaml

# explicit options
fibgen -dir ./myservice -o openapi.json --openapi-version 3.0 ./...
Flags
Flag Default Description
-o stdout output file; extension (.yaml / .json) selects the format
-format from -o, else yaml output format: yaml | json
-dir . project directory to analyze
--openapi-version 3.1 spec version: 3.1 or 3.0
--title module name API title
--doc-version 0.1.0 API document version
--quiet false suppress diagnostics on stderr

Anything the analyzer cannot resolve statically is reported on stderr as note: ... (suppress with --quiet).

What it detects

Routes
  • app.Get/Post/Put/Delete/Patch/Head/Options/Connect/Trace, All, Add(method, path, ...)
  • Group(prefix) with arbitrary nesting; prefixes are resolved through variable assignments and through routers passed as function parameters
  • Fiber paths → OpenAPI paths: :id{id}, :id? (optional), :id<int> (constraint maps to a type), * / + (wildcards)
Handlers (resolved to a function body)
  • named functions, controller method values (ctrl.Create), inline closures, function-typed variables, and statically resolvable handler factories (makeHandler(service))
  • project helper functions that receive the active Fiber context; actual arguments are propagated so respond(c, value) retains the concrete response type
Requests
  • body: c.BodyParser(&dto) (v2), c.Bind().Body(&dto) / .JSON(&dto) (v3)
  • query: c.QueryParser(&s) / c.Bind().Query(&s) (struct expansion via query: tags), and c.Query/QueryInt/QueryBool/QueryFloat("name")
  • path: from the route template, with the type upgraded by c.ParamsInt("id")
  • header: c.ReqHeaderParser(&s), c.Bind().Header(&s), c.Get("X-...")
Responses
  • c.JSON(x) / c.XML(x) → schema of x, status 200
  • c.Status(code).JSON(x) → status from code (literal or fiber.StatusCreated)
  • c.SendStatus(code), c.SendString(...), c.Status(code).Send..., c.Redirect(...)
  • multiple response shapes per status — when a handler returns different types depending on a flag (e.g. a short vs. full object on ?short=true), the alternatives are collected into a oneOf
  • ad-hoc JSON objectsc.JSON(fiber.Map{...}) / map[string]any{...} are expanded into an object with concrete properties; value types are inferred from the expressions, and nested literals and $refs are supported (e.g. {"message": string, "data": SomeStruct})
Types → JSON Schema
  • structs → reusable components ($ref), honoring json: tags, omitempty (drives required), and embedded/promoted fields
  • pointers → nullable (oneOf + null in 3.1, nullable: true in 3.0)
  • slices/arrays → array, maps → additionalProperties, []bytestring/byte
  • named types backed by a group of constants → enum
  • well-known types: time.Timedate-time, time.Duration, encoding/json.RawMessage, uuid.UUID, MongoDB primitive.ObjectID/DateTime, interface{}/any → free-form, fiber.Map → object
  • cross-package name collisions are disambiguated by package name (e.g. models.User vs. dto.User)

Example

A handler like this:

func (h *UserHandler) Create(c fiber.Ctx) error {
    var req CreateUserRequest
    if err := c.Bind().Body(&req); err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid body"})
    }
    user := h.svc.Create(req)
    return c.Status(fiber.StatusCreated).JSON(user)
}

…with the route app.Group("/api/v1").Group("/users").Post("/", h.Create) produces:

/api/v1/users:
  post:
    tags: [users]
    operationId: post_api_v1_users
    requestBody:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CreateUserRequest'
    responses:
      "201":
        description: Created
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      "400":
        description: Bad Request
        content:
          application/json:
            schema:
              type: object
              properties:
                error: { type: string }
              required: [error]

Two ready-to-run example projects (Fiber v2 and v3) live under examples/.

How it works

cmd/fibgen          CLI entrypoint
internal/analyzer   load packages, find routes, resolve group prefixes, analyze handler bodies
internal/schema     go/types -> version-neutral JSON Schema (+ component registry)
internal/model      framework-neutral API model (routes, params, responses)
internal/openapi    render the model to OpenAPI 3.0/3.1, serialize to YAML/JSON
internal/oapi       insertion-ordered map for deterministic, diff-friendly output
examples/v2, v3     example Fiber projects used by the test suite

Pipeline: analyzer.Analyzemodel.APIopenapi.Builder.Buildoapi.OMopenapi.Marshal.

Building

./build.sh            # current platform -> ./bin/fibgen
./build.sh all        # cross-compile linux/macos/windows (amd64 + arm64)
./build.sh install    # go install into $GOBIN / $GOPATH/bin

Windows: use build.bat with the same subcommands.

Limitations

Static analysis does not execute code, so there are honest boundaries:

  • Dynamic call targets. Helpers and handler factories are followed when their target can be resolved statically. Calls through interfaces, dependency-injection containers, or dynamically selected function values may retain only the information visible at the call site.
  • Dynamic paths. A path built from a non-constant string is skipped (with a note: on stderr).
  • Handlers behind DI/registries. If a handler cannot be resolved statically to a function (passed through an interface/container), its body is not analyzed and the route appears with a default 200 response.
  • Generics in response types are handled in a limited way.
  • Descriptions / summaries are not generated — there is no source for them without comments. This is a deliberate trade-off for zero-annotation operation.

Testing

go test ./...

The internal/openapi test analyzes the bundled examples/v2 and examples/v3 projects and validates the generated documents with kin-openapi.

Contributing

Issues and pull requests are welcome. Good first areas: interprocedural analysis (following response helpers), more binding patterns, and richer well-known type mappings.

License

MIT

Directories

Path Synopsis
cmd
fibgen command
Command fibgen generates an OpenAPI document from a Go + Fiber project using static analysis only — no source annotations required.
Command fibgen generates an OpenAPI document from a Go + Fiber project using static analysis only — no source annotations required.
internal
analyzer
Package analyzer performs static analysis of a Go + Fiber project to recover its HTTP routes and request/response types, with no source annotations.
Package analyzer performs static analysis of a Go + Fiber project to recover its HTTP routes and request/response types, with no source annotations.
model
Package model holds the analyzed, framework-neutral representation of an API that sits between the static analyzer and the OpenAPI emitter.
Package model holds the analyzed, framework-neutral representation of an API that sits between the static analyzer and the OpenAPI emitter.
oapi
Package oapi provides an insertion-ordered map that marshals deterministically to both YAML and JSON, which OpenAPI documents require for stable diffs.
Package oapi provides an insertion-ordered map that marshals deterministically to both YAML and JSON, which OpenAPI documents require for stable diffs.
openapi
Package openapi renders an analyzed model.API into an OpenAPI document (version 3.0 or 3.1) and serializes it to YAML or JSON.
Package openapi renders an analyzed model.API into an OpenAPI document (version 3.0 or 3.1) and serializes it to YAML or JSON.
schema
Package schema converts Go types (go/types) into an OpenAPI/JSON-Schema intermediate representation.
Package schema converts Go types (go/types) into an OpenAPI/JSON-Schema intermediate representation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL