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
Supported GORM Tags
The reader recognizes the following GORM struct tags:
column- Column nametype- SQL data type (e.g.,varchar(255),bigint)primaryKeyorprimary_key- Mark as primary keynot null- NOT NULL constraintautoIncrement- Auto-increment columndefault- Default valuesize- Column size/lengthindex- Create indexuniqueIndex- Create unique indexunique- Unique constraintforeignKey- Foreign key columnreferences- Referenced columnconstraint- 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.Modelembedded struct is automatically recognized and skipped - Table names are derived from struct names if
TableName()method is not present - Schema defaults to
publicif not specified inTableName() - 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