# 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 ```bash go install git.warky.dev/wdevs/relspecgo@latest ``` Or via Makefile: ```bash make install-relspecgo ``` ## Usage ### Basic Command ```bash relspecgo generate --input=sql/schema.dbml --output=pkg/models --orm=bun ``` ### Via Makefile ```bash 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 ```dbml 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 ```dbml 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` - `text` → `string` - `int`, `integer` → `int` - `bigint` → `int64` - `boolean`, `bool` → `bool` - `timestamp`, `datetime` → `time.Time` - `json`, `jsonb` → `json.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 ```go 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`: ```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 ```bash make generate-models ``` ### 3. Create Migrations ```bash make migrate-create NAME=add_products_table ``` Edit generated migration files in `sql/postgres/` and `sql/sqlite/` ### 4. Run Migrations ```bash make migrate-up ``` ### 5. Use in Code ```go 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 ```bash # 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: ```bash 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: ```go 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 - 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