Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SupaGo logo

SupaGo

Supabase toolkit for Go projects.

Installation

go install github.com/01JAMIL/supago.git/cmd/supago@latest

Quick Start

supago init

# configure .env with your database URL (SUPAGO_DATABASE_URL)

supago generate all

Workflow Example

Given a database with users and tasks tables, supago generate all produces:

internal/
├── adapters/
│   └── supago/
│       ├── models.go              # All Go structs
│       ├── users/
│       │   └── repository.go      # Repository implementation
│       └── tasks/
│           └── repository.go      # Repository implementation
├── users/
│   ├── service.go                 # Business logic (starting point)
│   └── handler.go                 # HTTP handlers (starting point)
├── tasks/
│   ├── service.go                 # Business logic (starting point)
│   └── handler.go                 # HTTP handlers (starting point)
└── json/
    └── json.go                    # JSON helpers (generated, DO NOT EDIT)

Generated models

// internal/adapters/supago/models.go
package supago

type User struct {
    ID        int64      `json:"id"`
    FullName  *string    `json:"fullName"`
    Email     *string    `json:"email"`
    CreatedAt time.Time  `json:"createdAt"`
}

type Task struct {
    ID        int64      `json:"id"`
    TaskName  *string    `json:"taskName"`
    IsDone    *bool      `json:"isDone"`
    UserID    *int64     `json:"userId"`
    CreatedAt time.Time  `json:"createdAt"`
}

Generated repository

// internal/adapters/supago/users/repository.go
package users

type Repository struct {
    pool *pgxpool.Pool
}

func NewRepository(pool *pgxpool.Pool) *Repository { ... }
func (r *Repository) List(ctx context.Context) ([]supago.User, error) { ... }
func (r *Repository) GetByID(ctx context.Context, id int64) (*supago.User, error) { ... }
func (r *Repository) Create(ctx context.Context, user *supago.User) error { ... }
func (r *Repository) Update(ctx context.Context, user *supago.User) error { ... }
func (r *Repository) Delete(ctx context.Context, id int64) error { ... }

Generated service & handler

// internal/users/service.go — starting point, modify as needed
package users

type Service struct {
    repo *usersrepo.Repository
}

func (s *Service) List(ctx context.Context) ([]supago.User, error) {
    return s.repo.List(ctx)
}
// internal/users/handler.go — starting point, modify as needed
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
    items, err := h.svc.List(r.Context())
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    json.Write(w, http.StatusOK, items)
}

Architecture

Layer Path Ownership
Infrastructure internal/adapters/supago/ Generated by SupaGo, DO NOT EDIT
Application internal/{table}/ Generated as starting point, modify freely

The infrastructure layer owns the models and repository implementations. The application layer owns the services and handlers — generated once as a starting point, then fully owned by the developer.

Configuration

supago.yaml is generated by supago init:

version: 1

database:
  driver: postgres
  url: ${SUPAGO_DATABASE_URL}

generation:
  output: internal/adapters/supago

Custom queries

Custom queries let you generate repository methods for queries you define yourself, in addition to the standard CRUD operations.

Why custom queries

The generated CRUD repositories cover common operations (List, GetByID, Create, Update, Delete). Real applications also need lookups like "find a user by email" or "list posts by author". Custom queries generate those methods for you, with safe parameterized SQL.

Configuration

Define queries per table under generation.queries in supago.yaml:

generation:
  output: internal/adapters/supago
  queries:
    users:
      - name: FindByEmail
        where:
          - email = $1
      - name: FindByEmailAndName
        where:
          - email = $1
          - full_name = $2
      - name: ListByActive
        where:
          - active = $1
    posts:
      - name: ListByAuthor
        where:
          - author_id = $1

The query name determines the generated method and its return type:

  • Names starting with Find or Get generate a method returning a single item (*Model, using QueryRow).
  • Names starting with List generate a method returning a slice ([]Model, using Query).

Each where entry is a column OP $N condition. Column references are validated against the actual database schema.

CLI usage

Generate the repository methods for your configured queries:

supago generate query

This writes <outputDir>/<table>/queries.go for each configured table, extending the existing generated repository. Run supago generate all (or at least repository) once first so the base repositories exist.

If no queries are configured, the command prints a helpful message instead of failing.

Generated code

For the configuration above, supago generate query produces:

// internal/adapters/supago/users/queries.go
package users

func (r *Repository) FindByEmail(ctx context.Context, email string) (*supago.User, error) {
    row := r.pool.QueryRow(ctx, "SELECT id, full_name, email, created_at FROM users WHERE email = $1", email)
    // ...
}

func (r *Repository) ListByActive(ctx context.Context, active bool) ([]supago.User, error) {
    // ...
}

Generated methods use context.Context, the existing pgxpool.Pool abstraction, the generated models, and parameterized SQL — no string concatenation, so the queries are safe from SQL injection.

Current limitations

Custom queries are intentionally simple in the first iteration:

  • WHERE conditions only — no joins, subqueries, aggregations, or transactions.
  • Arguments are strictly positional ($1, $2, …, used sequentially).
  • No ORDER BY, LIMIT, or OFFSET.
  • Conditions are combined with AND.

These can be extended in future versions.

Environment

# .env
SUPAGO_DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres

Commands

Command Description
init Initialize SupaGo in an existing Go project
inspect Inspect the database schema and display tables, columns, types, and constraints
generate model Generate Go structs from database tables
generate repository Generate Go repositories with full CRUD per table
generate query Generate custom repository queries defined in supago.yaml
generate crud Generate services and HTTP handlers using net/http as a starting point
generate all Run the full generation pipeline (model, repository, crud)
version Print the version of SupaGo

License

MIT

About

SupaGo is a CLI tool that introspects your Supabase PostgreSQL database and generates idiomatic Go structs, reducing boilerplate and keeping your models in sync with your schema.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages