# GORM Writer

Generates Go source files with GORM model definitions from database schema information.

## Overview

The GORM Writer converts RelSpec's internal database model representation into Go source code with GORM struct definitions, complete with proper tags, relationships, and methods.

## Features

- Generates GORM-compatible Go structs
- Creates proper `gorm` struct tags
- Generates `TableName()` methods
- Adds relationship fields (belongs-to, has-many)
- Supports both single-file and multi-file output
- Auto-generates helper methods (optional)
- Maps SQL types to Go types
- Handles nullable fields with custom sql_types

## Usage

### Basic Example

```go
package main

import (
    "git.warky.dev/wdevs/relspecgo/pkg/models"
    "git.warky.dev/wdevs/relspecgo/pkg/writers"
    "git.warky.dev/wdevs/relspecgo/pkg/writers/gorm"
)

func main() {
    // Assume db is a *models.Database from a reader
    options := &writers.WriterOptions{
        OutputPath:  "models.go",
        PackageName: "models",
    }

    writer := gorm.NewWriter(options)
    err := writer.WriteDatabase(db)
    if err != nil {
        panic(err)
    }
}
```

### CLI Examples

```bash
# Generate GORM models from PostgreSQL database (single file)
relspec --input pgsql \
  --conn "postgres://localhost/mydb" \
  --output gorm \
  --out-file models.go \
  --package models

# Generate GORM models with multi-file output (one file per table)
relspec --input json \
  --in-file schema.json \
  --output gorm \
  --out-file models/ \
  --package models

# Convert DBML to GORM models
relspec --input dbml --in-file schema.dbml --output gorm --out-file models.go
```

## Output Modes

### Single File Mode

Generates all models in one file:

```bash
relspec --input pgsql --conn "..." --output gorm --out-file models.go
```

### Multi-File Mode

Generates one file per table (auto-detected when output is a directory):

```bash
relspec --input pgsql --conn "..." --output gorm --out-file models/
```

Files are named: `sql_{schema}_{table}.go`

## Generated Code Example

```go
package models

import (
    "time"
    sql_types "git.warky.dev/wdevs/sql_types"
)

type ModelUser struct {
    ID        int64                `gorm:"column:id;type:bigint;primaryKey;autoIncrement" json:"id"`
    Username  string               `gorm:"column:username;type:varchar(50);not null;uniqueIndex" json:"username"`
    Email     string               `gorm:"column:email;type:varchar(100);not null" json:"email"`
    CreatedAt time.Time            `gorm:"column:created_at;type:timestamp;not null;default:now()" json:"created_at"`

    // Relationships
    Pos []*ModelPost `gorm:"foreignKey:UserID;references:ID;constraint:OnDelete:CASCADE" json:"pos,omitempty"`
}

func (ModelUser) TableName() string {
    return "public.users"
}

type ModelPost struct {
    ID        int64           `gorm:"column:id;type:bigint;primaryKey" json:"id"`
    UserID    int64           `gorm:"column:user_id;type:bigint;not null" json:"user_id"`
    Title     string          `gorm:"column:title;type:varchar(200);not null" json:"title"`
    Content   sql_types.SqlString `gorm:"column:content;type:text" json:"content,omitempty"`

    // Belongs to
    Use *ModelUser `gorm:"foreignKey:UserID;references:ID" json:"use,omitempty"`
}

func (ModelPost) TableName() string {
    return "public.posts"
}
```

## Writer Options

### Metadata Options

Configure the writer behavior using metadata in `WriterOptions`:

```go
options := &writers.WriterOptions{
    OutputPath:  "models.go",
    PackageName: "models",
    Metadata: map[string]interface{}{
        "multi_file":      true,  // Enable multi-file mode
        "populate_refs":   true,  // Populate RefDatabase/RefSchema
        "generate_get_id_str": true, // Generate GetIDStr() methods
    },
}
```

## Type Mapping

| SQL Type | Go Type | Notes |
|----------|---------|-------|
| bigint, int8 | int64 | - |
| integer, int, int4 | int | - |
| smallint, int2 | int16 | - |
| varchar, text | string | Not nullable |
| varchar, text (nullable) | sql_types.SqlString | Nullable |
| boolean, bool | bool | - |
| timestamp, timestamptz | time.Time | - |
| numeric, decimal | float64 | - |
| uuid | string | - |
| json, jsonb | string | - |

## Relationship Generation

The writer automatically generates relationship fields:

- **Belongs-to**: Generated for tables with foreign keys
- **Has-many**: Generated for tables referenced by foreign keys
- Relationship field names use 3-letter prefixes
- Includes proper `gorm` tags with `foreignKey` and `references`

## Notes

- Model names are prefixed with "Model" (e.g., `ModelUser`)
- Nullable columns use `sql_types.SqlString`, `sql_types.SqlInt64`, etc.
- Generated code is auto-formatted with `go fmt`
- JSON tags are automatically added
- Supports schema-qualified table names in `TableName()` method
