7.3 KiB
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:
- Read
sql/schema.dbml - Generate BUN models in
pkg/models/ - 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)→stringtext→stringint,integer→intbigint→int64boolean,bool→booltimestamp,datetime→time.Timejson,jsonb→json.RawMessageor 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 aliasbun:"id,pk"- Primary keybun:"username,unique"- Unique constraintbun:"password,notnull"- NOT NULL constraintbun:"role,default:'user'"- Default valuebun:"type:varchar(255)"- Explicit column typebun:"deleted_at,soft_delete"- Soft delete supportbun:"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
- Single Source of Truth: Keep DBML as the source of truth for schema
- Regenerate After Changes: Always run
make generate-modelsafter DBML changes - Don't Edit Generated Files: Modify DBML instead, then regenerate
- Version Control: Commit both DBML and generated models
- Migrations: Create migrations for schema changes
- Relationships: Define relationships in DBML for proper code generation
- 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
- Type Safety: Generated Go structs are type-safe
- Consistency: Same schema definition for all models
- Documentation: DBML serves as schema documentation
- Validation: Catches schema errors before runtime
- IDE Support: Full IDE autocomplete and type checking
- Relationships: Automatic relationship setup
- 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 tidyto 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
- relspecgo: https://git.warky.dev/wdevs/relspecgo
- DBML Syntax: https://dbml.dbdiagram.io/docs/
- BUN ORM: https://bun.uptrace.dev/
- ResolveSpec: https://github.com/bitechdev/ResolveSpec