Skip to content

Migration from Huma

MeGaNeKo edited this page Mar 20, 2026 · 1 revision

Migration from Huma

This guide covers the key changes when migrating from Huma v2 to Neoma.

Import Paths

Huma v2 Neoma
github.com/danielgtaylor/huma/v2 github.com/MeGaNeKoS/neoma/neoma
github.com/danielgtaylor/huma/v2/adapters/humachi github.com/MeGaNeKoS/neoma/adapters/neomachi/v5
github.com/danielgtaylor/huma/v2/humatest github.com/MeGaNeKoS/neoma/neomatest
github.com/danielgtaylor/huma/v2/humacli github.com/MeGaNeKoS/neoma/neomacli
github.com/danielgtaylor/huma/v2/sse github.com/MeGaNeKoS/neoma/sse
(no equivalent) github.com/MeGaNeKoS/neoma/core
(no equivalent) github.com/MeGaNeKoS/neoma/errors
(no equivalent) github.com/MeGaNeKoS/neoma/middleware
(no equivalent) github.com/MeGaNeKoS/neoma/pipeline

Type Locations

Types like Context, Operation, Config, and Schema live in the core package. Registration functions (NewAPI, Register, Get, Post, etc.) live in the neoma package. There are no type aliases; import core directly for type references.

// Huma v2
var op huma.Operation

// Neoma
import "github.com/MeGaNeKoS/neoma/core"
var op core.Operation

API Construction

// Huma v2
router := chi.NewMux()
api := humachi.New(router, huma.DefaultConfig("My API", "1.0.0"))

// Neoma
router := chi.NewMux()
adapter := neomachi.NewAdapter(router)
config := neoma.DefaultConfig("My API", "1.0.0")
api := neoma.NewAPI(config, adapter)

Error Handling

Huma v2 had a hardcoded error model. Neoma uses a pluggable ErrorHandler interface with two built-in implementations:

import "github.com/MeGaNeKoS/neoma/errors"

config.ErrorHandler = errors.NewRFC9457Handler()  // RFC 9457 (default)
config.ErrorHandler = errors.NewNoopHandler()      // No error schema

Convenience Function Renames

The naming convention changed from status-code-in-name to descriptive names. Functions moved to the errors package:

Huma v2 Neoma
huma.Error400BadRequest(msg) errors.ErrorBadRequest(msg)
huma.Error401Unauthorized(msg) errors.ErrorUnauthorized(msg)
huma.Error403Forbidden(msg) errors.ErrorForbidden(msg)
huma.Error404NotFound(msg) errors.ErrorNotFound(msg)
huma.Error409Conflict(msg) errors.ErrorConflict(msg)
huma.Error422UnprocessableEntity(msg) errors.ErrorUnprocessableEntity(msg)
huma.Error429TooManyRequests(msg) errors.ErrorTooManyRequests(msg)
huma.Error500InternalServerError(msg) errors.ErrorInternalServerError(msg)

Group API

Groups moved to the middleware package:

// Huma v2
grp := api.Group("/v1")

// Neoma
import "github.com/MeGaNeKoS/neoma/middleware"
grp := middleware.NewGroup(api, "/v1")

Testing

The test API uses a generic Do method instead of per-method helpers:

// Huma v2
_, api := humatest.New(t, huma.DefaultConfig("Test", "1.0.0"))
resp := api.Get("/items")

// Neoma
_, api := neomatest.New(t)
resp := api.Do("GET", "/items")

neomatest.New accepts an optional core.Config. Without one, it uses neoma.DefaultConfig("Test API", "1.0.0").

Config Default Changes

Setting Huma v2 Neoma
AllowAdditionalPropertiesByDefault false true
FieldsOptionalByDefault false true
Docs path /docs /public/docs

Key Differences Summary

Area Huma v2 Neoma
Types Root huma package core package (no aliases)
Registration Root huma package neoma package
Adapter humachi.New(router, config) neomachi.NewAdapter(router) + neoma.NewAPI(config, adapter)
Errors Hardcoded model Pluggable ErrorHandler
Error functions huma.Error404NotFound errors.ErrorNotFound
Groups api.Group("/v1") middleware.NewGroup(api, "/v1")
Test requests api.Get("/path") api.Do("GET", "/path")
Internal spec Not available core.InternalSpecConfig
Pipeline Not available pipeline package
Auto-discovery Not available neoma-discover tool

Migration Checklist

  1. Update go.mod to use github.com/MeGaNeKoS/neoma
  2. Update all import paths (see table above)
  3. Change adapter construction to separate NewAdapter + NewAPI calls
  4. Move error calls from huma.Error* to errors.Error* with new names
  5. Update group creation from api.Group() to middleware.NewGroup(api)
  6. Replace test api.Get/api.Post calls with api.Do("GET", ...)
  7. If using custom error models, implement core.ErrorHandler
  8. Update docs path references from /docs to /public/docs
  9. Run tests to verify behavior

Clone this wiki locally