# 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 a DBML schema (default: resolvespec types) relspec convert --from dbml --from-path schema.dbml \ --to gorm --to-path models.go --package models # Use standard library database/sql nullable types instead of resolvespec relspec convert --from dbml --from-path schema.dbml \ --to gorm --to-path models.go --package models \ --types stdlib # Explicitly select resolvespec types (same as omitting --types) relspec convert --from pgsql --from-conn "postgres://localhost/mydb" \ --to gorm --to-path models.go --package models \ --types resolvespec # Multi-file output (one file per table) relspec convert --from json --from-path schema.json \ --to gorm --to-path models/ --package models ``` ## 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 Examples ### Default — resolvespec types (`--types resolvespec`) ```go package models import ( sql_types "github.com/bitechdev/ResolveSpec/pkg/spectypes" ) type ModelUser struct { ID string `gorm:"column:id;type:uuid;primaryKey" json:"id"` Username string `gorm:"column:username;type:text;not null" json:"username"` Email sql_types.SqlString `gorm:"column:email;type:text" json:"email,omitempty"` Tags sql_types.SqlStringArray `gorm:"column:tags;type:text[];not null;default:'{}'" json:"tags"` CreatedAt sql_types.SqlTimeStamp `gorm:"column:created_at;type:timestamptz;not null;default:now()" json:"created_at"` } func (ModelUser) TableName() string { return "public.users" } ``` ### Standard library — `--types stdlib` ```go package models import ( "database/sql" "time" ) type ModelUser struct { ID string `gorm:"column:id;type:uuid;primaryKey" json:"id"` Username string `gorm:"column:username;type:text;not null" json:"username"` Email sql.NullString `gorm:"column:email;type:text" json:"email,omitempty"` Tags []string `gorm:"column:tags;type:text[];not null;default:'{}'" json:"tags"` CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null;default:now()" json:"created_at"` } func (ModelUser) TableName() string { return "public.users" } ``` ## Writer Options ### NullableTypes Controls which Go package is used for nullable column types. Set via the `--types` CLI flag or `WriterOptions.NullableTypes`: ```go // Use resolvespec types (default — omit NullableTypes or set to "resolvespec") options := &writers.WriterOptions{ OutputPath: "models.go", PackageName: "models", NullableTypes: writers.NullableTypeResolveSpec, } // Use standard library database/sql types options := &writers.WriterOptions{ OutputPath: "models.go", PackageName: "models", NullableTypes: writers.NullableTypeStdlib, } ``` ### Metadata Options Configure additional writer behavior using metadata in `WriterOptions`: ```go options := &writers.WriterOptions{ OutputPath: "models.go", PackageName: "models", Metadata: map[string]any{ "multi_file": true, // Enable multi-file mode "populate_refs": true, // Populate RefDatabase/RefSchema "generate_get_id_str": true, // Generate GetIDStr() methods }, } ``` ## Type Mapping The nullable type package is selected with `--types` (or `WriterOptions.NullableTypes`). | SQL Type | NOT NULL — both | Nullable — resolvespec | Nullable — stdlib | |---|---|---|---| | `bigint` | `int64` | `SqlInt64` | `sql.NullInt64` | | `integer` | `int32` | `SqlInt32` | `sql.NullInt32` | | `smallint` | `int16` | `SqlInt16` | `sql.NullInt16` | | `text`, `varchar` | `string` | `SqlString` | `sql.NullString` | | `boolean` | `bool` | `SqlBool` | `sql.NullBool` | | `timestamp`, `timestamptz` | `time.Time` | `SqlTimeStamp` | `sql.NullTime` | | `numeric`, `decimal` | `float64` | `SqlFloat64` | `sql.NullFloat64` | | `uuid` | `string` | `SqlUUID` | `sql.NullString` | | `jsonb` | `string` | `SqlString` | `sql.NullString` | | `text[]` | `SqlStringArray` | `SqlStringArray` | `[]string` | | `integer[]` | `SqlInt32Array` | `SqlInt32Array` | `[]int32` | | `uuid[]` | `SqlUUIDArray` | `SqlUUIDArray` | `[]string` | | `vector` | `SqlVector` | `SqlVector` | `[]float32` | ## 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. by default; pass `--types stdlib` to use `sql.NullString`, `sql.NullInt64`, etc. instead - Array columns use `sql_types.SqlStringArray`, `sql_types.SqlInt32Array`, etc. by default; `--types stdlib` produces plain Go slices (`[]string`, `[]int32`, …) - Generated code is auto-formatted with `go fmt` - JSON tags are automatically added - Supports schema-qualified table names in `TableName()` method