* Fix pgsql reader double-quoting defaults: normalizePostgresDefault strips surrounding SQL string literal quotes from column_default before storing, matching the convention used by every other reader. * Add NullableTypes field to WriterOptions with NullableTypeResolveSpec (default) and NullableTypeStdlib constants. * Both bun and gorm TypeMappers now accept a typeStyle parameter. stdlib mode produces sql.NullString/NullInt32/NullTime etc. for nullable scalars, plain Go slices for arrays, and time.Time for NOT NULL timestamps. Default resolvespec behaviour is unchanged. * Add --types flag to convert and split commands. * Update bun/README.md and gorm/README.md with side-by-side generated code examples, updated type mapping tables, and Writer Options documentation.
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
bunstruct 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
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
# 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)
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
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 aliascolumn- Column name (auto-derived if not specified)pk- Primary keyautoincrement- Auto-incrementnotnull- NOT NULL constraintunique- Unique constraintdefault- Default valuerel- Relationship definitiontype- 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:
// 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
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 stdlibto usesql.NullString,sql.NullTime, etc. instead - Array columns use
resolvespec_common.SqlStringArray,resolvespec_common.SqlInt32Array, etc. by default;--types stdlibproduces 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