296 lines
7.3 KiB
Markdown
296 lines
7.3 KiB
Markdown
# 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
|