GoCRUD is a powerful Go module that extends Huma to automatically generate CRUD APIs with built-in support for input validation and customizable hooks. It simplifies API development by automating repetitive tasks, allowing you to focus on your business logic.
- Seamless Huma Integration: Works effortlessly with the Huma API framework.
- Automatic CRUD Generation: Instantly generate RESTful endpoints for your models.
- Input Validation: Automatically validates input data.
- Customizable Hooks: Add custom logic before or after CRUD operations.
- Clean and Maintainable: Keeps your codebase organized and easy to maintain.
- Go 1.22 or higher
- A project using Huma
Install GoCRUD using go get
:
go get github.com/ckoliber/gocrud
- Define Your Model:
type User struct {
_ struct{} `db:"users" json:"-"`
ID *int `db:"id" json:"id" required:"false"`
Name *string `db:"name" json:"name" required:"false" maxLength:"30" example:"David" doc:"User name"`
Age *int `db:"age" json:"age" required:"false" minimum:"1" maximum:"120" example:"25" doc:"User age from 1 to 120"`
}
- Register Your Model with GoCRUD:
package main
import (
"github.com/danielgtaylor/huma/v2"
"github.com/ckoliber/gocrud"
"database/sql"
_ "github.com/lib/pq" // Example: PostgreSQL driver
)
func main() {
db, _ := sql.Open("postgres", "your-dsn-here")
api := huma.New("My API", "1.0.0")
repo := gocrud.NewSQLRepository[User](db)
gocrud.Register(api, repo, &gocrud.Config[User]{})
api.Serve()
}
- Run Your API:
Start your application, and GoCRUD will generate the following endpoints for the User
model:
GET /users
- List all usersPOST /users
- Create a new userGET /users/{id}
- Get a specific userPUT /users/{id}
- Update a userDELETE /users/{id}
- Delete a user
GoCRUD provides a flexible configuration system to customize API behavior:
type Config[Model any] struct {
GetMode Mode // Configure GET behavior (e.g., single or bulk)
PutMode Mode // Configure PUT behavior
PostMode Mode // Configure POST behavior
DeleteMode Mode // Configure DELETE behavior
// Add before hooks for custom logic
BeforeGet func(ctx context.Context, where *map[string]any, order *map[string]any, limit *int, skip *int) error
BeforePut func(ctx context.Context, models *[]Model) error
BeforePost func(ctx context.Context, models *[]Model) error
BeforeDelete func(ctx context.Context, where *map[string]any) error
// Add after hooks for custom logic
AfterGet func(ctx context.Context, models *[]Model) error
AfterPut func(ctx context.Context, models *[]Model) error
AfterPost func(ctx context.Context, models *[]Model) error
AfterDelete func(ctx context.Context, models *[]Model) error
}
config := &gocrud.Config[User]{
BeforePost: func(ctx context.Context, models *[]User) error {
for _, user := range *models {
if user.Age < 18 {
return fmt.Errorf("user must be at least 18 years old")
}
}
return nil
},
}
GoCRUD supports filtering through relationships. You can query parent entities based on their related entities' properties:
type User struct {
_ struct{} `db:"users" json:"-"`
ID *int `db:"id" json:"id"`
Name *string `db:"name" json:"name"`
Documents []Document `db:"documents" src:"id" dest:"userId" table:"documents" json:"-"`
}
type Document struct {
_ struct{} `db:"documents" json:"-"`
ID *int `db:"id" json:"id"`
Title string `db:"title" json:"title"`
UserID int `db:"userId" json:"userId"`
}
You can then filter users by their documents:
GET /users?where={"documents":{"title":{"_eq":"Doc4"}}}
This will return users who have documents with title "Doc4".
You can define custom operations for your model fields by implementing the Operations
method:
type ID int
func (_ *ID) Operations() map[string]func(string, ...string) string {
return map[string]func(string, ...string) string{
"_regexp": func(key string, values ...string) string {
return fmt.Sprintf("%s REGEXP %s", key, values[0])
},
"_iregexp": func(key string, values ...string) string {
return fmt.Sprintf("%s IREGEXP %s", key, values[0])
},
}
}
type User struct {
_ struct{} `db:"users" json:"-"`
ID *ID `db:"id" json:"id"`
Name *string `db:"name" json:"name"`
}
Now you can use these custom operations in your queries:
GET /users?where={"id":{"_regexp":"5"}}
The operations are type-safe and validated against the field's defined operations.
We welcome contributions! To contribute:
- Fork the repository.
- Create a feature branch:
git checkout -b feature/my-feature
. - Commit your changes:
git commit -m "Add my feature"
. - Push to the branch:
git push origin feature/my-feature
. - Open a pull request.
This project is licensed under the MIT License. See the LICENSE file for details.
- Built on top of the Huma framework.
- Inspired by best practices in the Go community.
- Thanks to all contributors who have helped shape GoCRUD.
Made with β€οΈ by KoLiBer