GORM Reader
Reads Go source files containing GORM model definitions and extracts database schema information.
Overview
The GORM Reader parses Go source code files that define GORM models (structs with gorm struct tags) and converts them into RelSpec's internal database model representation. It supports reading from individual files or entire directories.
Features
- Parses GORM struct tags to extract column definitions
- Extracts table names from
TableName() methods
- Identifies primary keys, foreign keys, and indexes
- Supports relationship detection (has-many, belongs-to)
- Handles both single files and directories
Usage
Basic Example
package main
import (
"fmt"
"git.warky.dev/wdevs/relspecgo/pkg/readers"
"git.warky.dev/wdevs/relspecgo/pkg/readers/gorm"
)
func main() {
// Read from a single file
options := &readers.ReaderOptions{
FilePath: "/path/to/models.go",
}
reader := gorm.NewReader(options)
db, err := reader.ReadDatabase()
if err != nil {
panic(err)
}
fmt.Printf("Found %d schemas\n", len(db.Schemas))
}
Reading from Directory
// Read all .go files from a directory
options := &readers.ReaderOptions{
FilePath: "/path/to/models/",
}
reader := gorm.NewReader(options)
db, err := reader.ReadDatabase()
if err != nil {
panic(err)
}
CLI Example
# Read GORM models and convert to JSON
relspec --input gorm --in-file models/ --output json --out-file schema.json
# Convert GORM models to Bun
relspec --input gorm --in-file models.go --output bun --out-file bun_models.go
The reader recognizes the following GORM struct tags:
column - Column name
type - SQL data type (e.g., varchar(255), bigint)
primaryKey or primary_key - Mark as primary key
not null - NOT NULL constraint
autoIncrement - Auto-increment column
default - Default value
size - Column size/length
index - Create index
uniqueIndex - Create unique index
unique - Unique constraint
foreignKey - Foreign key column
references - Referenced column
constraint - Constraint behavior (OnDelete, OnUpdate)
Example GORM Model
package models
import (
"time"
"gorm.io/gorm"
)
type ModelUser struct {
gorm.Model
ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement"`
Username string `gorm:"column:username;type:varchar(50);not null;uniqueIndex"`
Email string `gorm:"column:email;type:varchar(100);not null"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:now()"`
// Relationships
Posts []*ModelPost `gorm:"foreignKey:UserID;references:ID;constraint:OnDelete:CASCADE"`
}
func (ModelUser) TableName() string {
return "public.users"
}
type ModelPost struct {
ID int64 `gorm:"column:id;type:bigint;primaryKey"`
UserID int64 `gorm:"column:user_id;type:bigint;not null"`
Title string `gorm:"column:title;type:varchar(200);not null"`
Content string `gorm:"column:content;type:text"`
// Belongs-to relationship
User *ModelUser `gorm:"foreignKey:UserID;references:ID"`
}
func (ModelPost) TableName() string {
return "public.posts"
}
Notes
- Test files (ending in
_test.go) are automatically excluded
- The
gorm.Model embedded struct is automatically recognized and skipped
- Table names are derived from struct names if
TableName() method is not present
- Schema defaults to
public if not specified in TableName()
- Relationships are inferred from GORM relationship tags
Limitations
- Complex relationship types (many-to-many with join tables) may need manual verification
- Custom GORM types may not be fully supported
- Some advanced GORM features may not be captured