Skip to content

Gompose – A ready-to-run and flexible backend framework for Go that gets your services up and running in seconds.

License

Notifications You must be signed in to change notification settings

Lumicrate/gompose

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gompose

Gompose is a Go framework for quickly building RESTful APIs with support for multiple HTTP engines and databases (Postgres, MongoDB, etc). It provides features like CRUD handlers, entity hooks, middlewares, authentication, i18n, and automatic Swagger documentation.


Features

  • Define entities as Go structs with tags
  • Supports Postgres (GORM) and MongoDB adapters(more will be added in future!)
  • Multiple HTTP engine adapters support(for now it's only Gin but more will be added in future)
  • CRUD endpoints autogenerated per entity
  • Middleware support (logging, rate limiting, etc)
  • Custom Middlewares are also supported as well
  • Entity lifecycle hooks (beforeSave, afterDelete, etc)
  • Pagination, filtering, sorting support
  • Authentication and Authorization with login and register routes(JWT for now but more will be added in future)
  • Automatic Swagger/OpenAPI 3.0 documentation with interactive UI
  • Internationalization (i18n) and translations with YAML/JSON files

Installation

go get github.com/Lumicrate/gompose

Install Dependencies

go mod tidy

Usage

Setup

Setting up Gompose is so easy and quick you only have to tell what you want, here is the example of using Gompose!

package main

import (
    "github.com/Lumicrate/gompose/core"
    "github.com/Lumicrate/gompose/db/postgres"
    "github.com/Lumicrate/gompose/http/gin"
    "github.com/Lumicrate/gompose/middlewares"
)

// Define your entities
type User struct {
    ID    int    `json:"id" gorm:"primaryKey;autoIncrement"` // make sure to include ID field for your entities
    Name  string `json:"name"`
    Email string `json:"email"`
}

// define your hooks

func (u *User) BeforeCreate() error {
	if !strings.Contains(u.Email, "@") {
		return errors.New("invalid email format")
	}
	return nil
}

// create your custom middlewares
func CORSMiddleware() http.MiddlewareFunc {
	return func(ctx http.Context) {
		ctx.SetHeader("Access-Control-Allow-Origin", "*")
		ctx.SetHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		ctx.SetHeader("Access-Control-Allow-Headers", "Authorization, Content-Type")

		if ctx.Method() == "OPTIONS" {
			ctx.SetStatus(204)
			ctx.Abort()
			return
		}
		ctx.Next()
	}
}

func main() {
    dsn := "host=localhost user=user password=password dbname=mydb port=5432 sslmode=disable" // set up the data source name
    dbAdapter := postgres.New(dsn) // make your data adapter
    httpEngine := ginadapter.New(8080) // make an http engine with the port

    app := core.NewApp(). // create a new app
        AddEntity(User{}). // add your entities
        UseDB(dbAdapter). // register your database with your db adapter
        UseHTTP(httpEngine). // register your http engine 
        RegisterMiddleware(middlewares.LoggingMiddleware()). // use built-in middlewares
        RegisterMiddleware(CORSMiddleware()) // use your custom middleware

    app.Run() // run your application
}

Auth Routes & Route Protection

By following the setup shown below, two authentication routes will automatically be registered:

  • POST /auth/login
  • POST /auth/register

These endpoints are enabled when you initialize the authProvider using the jwt.NewJWTAuthProvider() method.

You can customize how long JWT tokens remain valid using the SetTokenTTL() method:

authProvider := jwt.NewJWTAuthProvider("SecretKEY", dbAdapter).
	SetUserModel(&User{}).
	SetTokenTTL(time.Hour * 1) // Token valid for 1 hour

If you don’t set this explicitly, a default expiration time (3 days) will be used.

Additionally, route protection is applied when you define which HTTP methods should be secured using the crud.Protect() function. For example:

AddEntity(Office{}, crud.Protect("POST", "PUT", "DELETE"))

This ensures that POST, PUT, and DELETE operations on the Office entity are protected and require valid authentication.

Alternatively, you can secure all HTTP methods for a given entity using:

AddEntity(Office{}, crud.ProtectAll())

Example:

func main() {
	// Configure Your database
	dsn := "host=localhost user=username password=password dbname=mydb port=5432 sslmode=disable"

	// Initialize DB adapter
	dbAdapter := postgres.New(dsn)

	// Initialize Gin HTTP adapter on port 8080
	httpEngine := ginadapter.New(8080)

	// Initialize JWT Provider 
	authProvider := jwt.NewJWTAuthProvider("SecretKEY", dbAdapter).
    SetUserModel(&User{}) // Set your customized user model

	// Create app instance
	app := core.NewApp().
		AddEntity(Office{}, crud.Protect("POST", "PUT", "DELETE")).
		//AddEntity(Office{}, crud.ProtectAll()).
		UseDB(dbAdapter).
		UseHTTP(httpEngine).
		UseAuth(authProvider)
	app.Run()
}

Supported HTTP Engines

  • Gin

More HTTP Engines will be added in future also, switching HTTP engines is as simple as changing the adapter used in UseHTTP.


Supported Databases

  • Postgres (via GORM)
  • MongoDB (using official MongoDB Go driver)

Change database adapters via UseDB.


Middleware

You can register custom middleware by implementing the http.MiddlewareFunc interface.
Note: The middleware signature has changed to support standard chaining. Instead of directly handling ctx, middleware now wraps a next handler.

Correct Middleware Structure

func LoggingMiddleware() http.MiddlewareFunc {
    return func(next http.HandlerFunc) http.HandlerFunc {
    return func(ctx http.Context) {
    start := time.Now()
    ctx.Next()
    duration := time.Since(start)
    log.Printf("[%s] %s %s %d %s",
    ctx.Method(), ctx.Path(), ctx.RemoteIP(), ctx.Status(), duration)
    
    next(ctx) // Call the next handler in the chain
    }
}

Register middleware with:

app.RegisterMiddleware(LoggingMiddleware())

Entity Hooks

Implement hooks on entities to run code before/after certain events:

type User struct {
    ID int `json:"id"`
    //...
}

func (u *User) BeforeCreate() error {
    // validation or processing
    return nil
}

func (u *User) AfterDelete() error {
    // cleanup or logging
    return nil
}

Pagination, Filtering, Sorting

Supported via query parameters on endpoints:

  • limit and offset for pagination
  • sort for sorting fields ascending/descending
  • Filters via query keys matching entity fields

Swagger (API Documentation)

Gompose now provides automatic OpenAPI 3.0 documentation and an interactive Swagger UI.

Accessing Swagger

Once your app is running, the following endpoints are available:

  • Raw OpenAPI JSON: [GET /swagger.json] Provides the full OpenAPI specification for your API.

  • Swagger UI: [GET /swagger-ui] Interactive API documentation with the ability to try endpoints directly from the browser.

Features

  • Auto-generates request and response schemas from your Go entities.
  • Converts :id path parameters to {id} automatically.
  • Shows all registered HTTP methods for each route.
  • Displays protected routes and allows JWT authentication via the “Authorize” button.

Example Usage

app := core.NewApp().
    AddEntity(User{}, crud.Protect("POST", "PUT", "DELETE")).
    UseDB(dbAdapter).
    UseHTTP(httpEngine).
    UseAuth(authProvider).
    UseSwagger() // Enable Swagger endpoints

app.Run()


CLI (Command Line Tool)

Starting from v1.4.0, Gompose ships with a CLI tool (gompose) to make scaffolding and setup even faster.

Setup

  • For Windows:
    go install github.com/Lumicrate/gompose@latest 
  • For Linux/macOS
    curl -sSL https://raw.githubusercontent.com/Lumicrate/gompose/main/install.sh | bash 

Available Commands

  • gompose config
    Generates a gompose.yaml configuration file.

    • If no parameters are provided, a default config will be generated.
    • Example:
      database:
        driver: postgres
        dsn: "host=localhost user=user password=password dbname=mydb port=5432 sslmode=disable"
      http:
        engine: gin
        port: 8080
      auth:
        secret: "SecretKEY"

    Parameters (Flags)

    You can override defaults using flags:

    Flag Default Value Description
    --db postgres Database driver. Options: postgres, mongodb.
    --dsn DSN string Database connection string (Postgres DSN or MongoDB URI).
    --dbname mydb Database name. Required for MongoDB, ignored for Postgres.
    --http gin HTTP engine. Currently only gin is supported.
    --port 8080 HTTP server port.
    --secret SecretKEY Secret key for authentication (used by JWT provider).

    Examples

    Generate default config:

    gompose config

    Generate config with MongoDB + custom port:

    gompose config --db=mongodb --dsn="mongodb://localhost:27017" --dbname=myproject --port=9090

    Generate config with custom secret:

    gompose config --secret="SuperSecret123"
  • gompose init
    Initializes a main.go file based on the settings in gompose.yaml.
    This scaffolds your app with database, HTTP engine, and authentication pre-wired.

  • gompose generate
    Generates CRUD boilerplate for your entities.

    Syntax

    gompose generate [EntityName] --fields fieldName:type,otherField:type
    • [EntityName]: The name of the entity struct (capitalized in Go).

    • --fields: A comma-separated list of fields with their types.

    Example

    gompose generate entity User --fields name:string,email:string

    This generates a file user.go in the entities/ package:

    package entities
    
    type User struct {
    ID    int    `json:"id" gorm:"primaryKey;autoIncrement"`
    Name  string `json:"name"`
    Email string `json:"email"`
    }

Internationalization (i18n)

Gompose now supports i18n / translations out of the box, using YAML/JSON files stored in a locales directory.

You can configure a default language, add custom language extractors (from headers, cookies, URL prefix), and dynamically translate strings with parameters.

Example fa.yml

- id: hello_world
  translation: "سلام دنیا"

- id: hello_name
  translation: "سلام {{.Name}}"

Example en.yml

- id: hello_world
  translation: "Hello World"

- id: hello_name
  translation: "Hello {{.Name}}"

Usage in App

httpEngine := ginadapter.New(8080)

app := core.NewApp().
    UseHTTP(httpEngine).
    UseI18n("./locales", "fa") // Load translations, default to Farsi

fmt.Println(app.T("hello_world")) 
// Output: "سلام دنیا"

fmt.Println(app.T("hello_name", map[string]any{"Name": "محمد"})) 
// Output: "سلام محمد"

fmt.Println(app.T("hello_name", "en", map[string]any{"Name":"Mohammad"})) 
// Output: "Hello Mohammad"

Changing Locale

app.SetLocale("en")

fmt.Println(app.T("hello_world"))
// Output: "Hello World"

Middleware

The i18n module also provides a middleware that automatically detects language from:

  • Accept-Language header

  • Cookies

  • URL prefix (configurable)

app.RegisterMiddleware(app.Localization.GetMiddleware())

Contribution

Contributions are welcome! Please submit issues and pull requests.


License

MIT License

About

Gompose – A ready-to-run and flexible backend framework for Go that gets your services up and running in seconds.

Resources

License

Stars

Watchers

Forks

Packages

No packages published