Files
whatshooked/tooldoc/RELSPECGO.md
Hein f9773bd07f
Some checks failed
CI / Test (1.23) (push) Failing after -22m46s
CI / Test (1.22) (push) Failing after -22m32s
CI / Build (push) Failing after -23m30s
CI / Lint (push) Failing after -23m12s
refactor(API): Relspect integration
2026-02-05 13:39:43 +02:00

7.3 KiB

relspecgo - DBML to BUN Model Generator

Overview

relspecgo is a code generator that converts DBML (Database Markup Language) schema files into BUN ORM models for Go. It automates the creation of model structs with proper BUN tags, relationships, and indexes.

Repository: https://git.warky.dev/wdevs/relspecgo

Installation

go install git.warky.dev/wdevs/relspecgo@latest

Or via Makefile:

make install-relspecgo

Usage

Basic Command

relspecgo generate --input=sql/schema.dbml --output=pkg/models --orm=bun

Via Makefile

make generate-models

This will:

  1. Read sql/schema.dbml
  2. Generate BUN models in pkg/models/
  3. Create proper Go structs with BUN tags

DBML Schema Format

Table Definition

Table users {
  id varchar(36) [primary key]
  username varchar(255) [unique, not null]
  email varchar(255) [unique, not null]
  password varchar(255) [not null]
  role varchar(50) [not null, default: 'user']
  active boolean [not null, default: true]
  created_at timestamp [not null, default: `now()`]
  updated_at timestamp [not null, default: `now()`]
  deleted_at timestamp [null]
  
  indexes {
    (deleted_at) [name: 'idx_users_deleted_at']
  }
}

Relationships

Table api_keys {
  id varchar(36) [primary key]
  user_id varchar(36) [not null, ref: > users.id]
  ...
}

// Explicit relationship with cascade delete
Ref: api_keys.user_id > users.id [delete: cascade]

Supported Field Types

  • varchar(n)string
  • textstring
  • int, integerint
  • bigintint64
  • boolean, boolbool
  • timestamp, datetimetime.Time
  • json, jsonbjson.RawMessage or custom type

Field Attributes

  • [primary key] → BUN primary key tag
  • [not null] → Required field
  • [unique] → Unique constraint
  • [default: value] → Default value
  • [note: 'text'] → Documentation comment
  • [ref: > table.column] → Foreign key relationship

Generated BUN Models

Example Output

package models

import (
    "time"
    "github.com/uptrace/bun"
)

type User struct {
    bun.BaseModel `bun:"table:users,alias:u"`
    
    ID        string    `bun:"id,pk,type:varchar(36)" json:"id"`
    Username  string    `bun:"username,unique,notnull,type:varchar(255)" json:"username"`
    Email     string    `bun:"email,unique,notnull,type:varchar(255)" json:"email"`
    Password  string    `bun:"password,notnull,type:varchar(255)" json:"-"`
    FullName  string    `bun:"full_name,type:varchar(255)" json:"full_name,omitempty"`
    Role      string    `bun:"role,notnull,default:'user',type:varchar(50)" json:"role"`
    Active    bool      `bun:"active,notnull,default:true" json:"active"`
    CreatedAt time.Time `bun:"created_at,notnull,default:now()" json:"created_at"`
    UpdatedAt time.Time `bun:"updated_at,notnull,default:now()" json:"updated_at"`
    DeletedAt time.Time `bun:"deleted_at,soft_delete" json:"deleted_at,omitempty"`
    
    // Relationships
    APIKeys          []*APIKey          `bun:"rel:has-many,join:id=user_id" json:"api_keys,omitempty"`
    Hooks            []*Hook            `bun:"rel:has-many,join:id=user_id" json:"hooks,omitempty"`
    WhatsAppAccounts []*WhatsAppAccount `bun:"rel:has-many,join:id=user_id" json:"whatsapp_accounts,omitempty"`
}

BUN Tags

  • bun:"table:users,alias:u" - Table name and alias
  • bun:"id,pk" - Primary key
  • bun:"username,unique" - Unique constraint
  • bun:"password,notnull" - NOT NULL constraint
  • bun:"role,default:'user'" - Default value
  • bun:"type:varchar(255)" - Explicit column type
  • bun:"deleted_at,soft_delete" - Soft delete support
  • bun:"rel:has-many,join:id=user_id" - Has-many relationship

Project Structure

sql/
├── schema.dbml          # Main schema definition
├── postgres/            # PostgreSQL specific migrations
│   ├── 20240101_init.up.sql
│   └── 20240101_init.down.sql
└── sqlite/              # SQLite specific migrations
    ├── 20240101_init.up.sql
    └── 20240101_init.down.sql

pkg/
└── models/              # Generated BUN models
    ├── user.go
    ├── api_key.go
    ├── hook.go
    └── ...

Workflow

1. Define Schema

Create or update sql/schema.dbml:

Table products {
  id int [primary key, increment]
  name varchar(255) [not null]
  price decimal(10,2) [not null]
  created_at timestamp [not null, default: `now()`]
}

2. Generate Models

make generate-models

3. Create Migrations

make migrate-create NAME=add_products_table

Edit generated migration files in sql/postgres/ and sql/sqlite/

4. Run Migrations

make migrate-up

5. Use in Code

import "git.warky.dev/wdevs/whatshooked/pkg/models"

// Query with BUN
var users []models.User
err := db.NewSelect().
    Model(&users).
    Relation("APIKeys").
    Where("active = ?", true).
    Scan(ctx)

Best Practices

  1. Single Source of Truth: Keep DBML as the source of truth for schema
  2. Regenerate After Changes: Always run make generate-models after DBML changes
  3. Don't Edit Generated Files: Modify DBML instead, then regenerate
  4. Version Control: Commit both DBML and generated models
  5. Migrations: Create migrations for schema changes
  6. Relationships: Define relationships in DBML for proper code generation
  7. Indexes: Specify indexes in DBML for performance

Common Commands

# Generate models from DBML
make generate-models

# Create new migration
make migrate-create NAME=add_users_table

# Run migrations
make migrate-up

# Rollback migrations
make migrate-down

# Install relspecgo
make install-relspecgo

DBML to SQL Conversion

relspecgo can also generate SQL from DBML:

relspecgo sql --input=sql/schema.dbml --output=sql/postgres/schema.sql --dialect=postgres
relspecgo sql --input=sql/schema.dbml --output=sql/sqlite/schema.sql --dialect=sqlite

Advantages

  1. Type Safety: Generated Go structs are type-safe
  2. Consistency: Same schema definition for all models
  3. Documentation: DBML serves as schema documentation
  4. Validation: Catches schema errors before runtime
  5. IDE Support: Full IDE autocomplete and type checking
  6. Relationships: Automatic relationship setup
  7. Migration Friendly: Easy to track schema changes

Integration with ResolveSpec

Generated BUN models work seamlessly with ResolveSpec:

import (
    "github.com/bitechdev/ResolveSpec/pkg/restheadspec"
    "git.warky.dev/wdevs/whatshooked/pkg/models"
)

// Create handler with BUN
handler := restheadspec.NewHandlerWithBun(db)

// Models are automatically discovered from BUN's table names

Troubleshooting

Models Not Generated

  • Check DBML syntax
  • Ensure relspecgo is installed: make install-relspecgo
  • Verify input/output paths

Compilation Errors

  • Run go mod tidy to update dependencies
  • Check for missing imports
  • Verify BUN version compatibility

Relationship Issues

  • Ensure foreign keys are properly defined in DBML
  • Check Ref: declarations
  • Verify join conditions

References