refactor(API): ✨ Relspect integration
This commit is contained in:
295
tooldoc/RELSPECGO.md
Normal file
295
tooldoc/RELSPECGO.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user