# 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

```go
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

```go
// 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

```bash
# 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 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

```go
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
