# Bun Writer Generates Go source files with Bun model definitions from database schema information. ## Overview The Bun Writer converts RelSpec's internal database model representation into Go source code with Bun struct definitions, complete with proper tags, relationships, and table configuration. ## Features - Generates Bun-compatible Go structs - Creates proper `bun` struct tags - Adds relationship fields - Supports both single-file and multi-file output - Maps SQL types to Go types - Handles nullable fields with sql.Null* types - Generates table aliases ## 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/bun" ) func main() { options := &writers.WriterOptions{ OutputPath: "models.go", PackageName: "models", } writer := bun.NewWriter(options) err := writer.WriteDatabase(db) if err != nil { panic(err) } } ``` ### CLI Examples ```bash # Generate Bun models from a DBML schema (default: resolvespec types) relspec convert --from dbml --from-path schema.dbml \ --to bun --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 bun --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 bun --to-path models.go --package models \ --types resolvespec # Multi-file output (one file per table) relspec convert --from json --from-path schema.json \ --to bun --to-path models/ --package models ``` ## Generated Code Examples ### Default — resolvespec types (`--types resolvespec`) ```go package models import ( resolvespec_common "github.com/bitechdev/ResolveSpec/pkg/spectypes" "github.com/uptrace/bun" ) type User struct { bun.BaseModel `bun:"table:users,alias:u"` ID int64 `bun:"id,type:uuid,pk," json:"id"` Username string `bun:"username,type:text,notnull," json:"username"` Email resolvespec_common.SqlString `bun:"email,type:text,nullzero," json:"email"` Tags resolvespec_common.SqlStringArray `bun:"tags,type:text[],default:'{}',notnull," json:"tags"` CreatedAt resolvespec_common.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"` } ``` ### Standard library — `--types stdlib` ```go package models import ( "database/sql" "time" "github.com/uptrace/bun" ) type User struct { bun.BaseModel `bun:"table:users,alias:u"` ID string `bun:"id,type:uuid,pk," json:"id"` Username string `bun:"username,type:text,notnull," json:"username"` Email sql.NullString `bun:"email,type:text,nullzero," json:"email"` Tags []string `bun:"tags,type:text[],default:'{}',notnull," json:"tags"` CreatedAt time.Time `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"` } ``` ## Supported Bun Tags - `table` - Table name and alias - `column` - Column name (auto-derived if not specified) - `pk` - Primary key - `autoincrement` - Auto-increment - `notnull` - NOT NULL constraint - `unique` - Unique constraint - `default` - Default value - `rel` - Relationship definition - `type` - Explicit SQL type ## 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` | `SqlJSONB` | `sql.NullString` | | `text[]` | `SqlStringArray` | `SqlStringArray` | `[]string` | | `integer[]` | `SqlInt32Array` | `SqlInt32Array` | `[]int32` | | `uuid[]` | `SqlUUIDArray` | `SqlUUIDArray` | `[]string` | | `vector` | `SqlVector` | `SqlVector` | `[]float32` | \* In resolvespec mode, NOT NULL timestamps use `SqlTimeStamp` (not `time.Time`) unless the base type is a simple integer or boolean. In stdlib mode, NOT NULL timestamps use `time.Time`. ## 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 ```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 }, } ``` ## Notes - Model names are derived from table names (singularized, PascalCase) - Table aliases are auto-generated from table names - Nullable columns use `resolvespec_common.SqlString`, `resolvespec_common.SqlTimeStamp`, etc. by default; pass `--types stdlib` to use `sql.NullString`, `sql.NullTime`, etc. instead - Array columns use `resolvespec_common.SqlStringArray`, `resolvespec_common.SqlInt32Array`, etc. by default; `--types stdlib` produces plain Go slices (`[]string`, `[]int32`, …) - Multi-file mode: one file per table named `sql_{schema}_{table}.go` - Generated code is auto-formatted - JSON tags are automatically added