refactor: ♻️ change resolvspec types to build in sqltypes
This commit is contained in:
+19
-17
@@ -6,6 +6,8 @@ Generates Go source files with Bun model definitions from database schema inform
|
||||
|
||||
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.
|
||||
|
||||
With `--types sqltypes`, nullable fields use the [`pkg/sqltypes`](../../sqltypes/README.md) package.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates Bun-compatible Go structs
|
||||
@@ -46,19 +48,19 @@ func main() {
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate Bun models from a DBML schema (default: resolvespec types)
|
||||
# Generate Bun models from a DBML schema (default: baselib pointer 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
|
||||
# Use standard library database/sql nullable types instead
|
||||
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)
|
||||
# Select sqltypes package types (git.warky.dev/wdevs/relspecgo/pkg/sqltypes)
|
||||
relspec convert --from pgsql --from-conn "postgres://localhost/mydb" \
|
||||
--to bun --to-path models.go --package models \
|
||||
--types resolvespec
|
||||
--types sqltypes
|
||||
|
||||
# Multi-file output (one file per table)
|
||||
relspec convert --from json --from-path schema.json \
|
||||
@@ -67,24 +69,24 @@ relspec convert --from json --from-path schema.json \
|
||||
|
||||
## Generated Code Examples
|
||||
|
||||
### Default — resolvespec types (`--types resolvespec`)
|
||||
### sqltypes package types (`--types sqltypes`)
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
resolvespec_common "github.com/bitechdev/ResolveSpec/pkg/spectypes"
|
||||
sql_types "git.warky.dev/wdevs/relspecgo/pkg/sqltypes"
|
||||
"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"`
|
||||
ID int64 `bun:"id,type:uuid,pk," json:"id"`
|
||||
Username string `bun:"username,type:text,notnull," json:"username"`
|
||||
Email sql_types.SqlString `bun:"email,type:text,nullzero," json:"email"`
|
||||
Tags sql_types.SqlStringArray `bun:"tags,type:text[],default:'{}',notnull," json:"tags"`
|
||||
CreatedAt sql_types.SqlTimeStamp `bun:"created_at,type:timestamptz,default:now(),notnull," json:"created_at"`
|
||||
}
|
||||
```
|
||||
|
||||
@@ -126,7 +128,7 @@ type User struct {
|
||||
|
||||
The nullable type package is selected with `--types` (or `WriterOptions.NullableTypes`).
|
||||
|
||||
| SQL Type | NOT NULL (both) | Nullable — resolvespec | Nullable — stdlib |
|
||||
| SQL Type | NOT NULL (both) | Nullable — sqltypes | Nullable — stdlib |
|
||||
|---|---|---|---|
|
||||
| `bigint` | `int64` | `SqlInt64` | `sql.NullInt64` |
|
||||
| `integer` | `int32` | `SqlInt32` | `sql.NullInt32` |
|
||||
@@ -142,7 +144,7 @@ The nullable type package is selected with `--types` (or `WriterOptions.Nullable
|
||||
| `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`.
|
||||
\* In sqltypes 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
|
||||
|
||||
@@ -151,11 +153,11 @@ The nullable type package is selected with `--types` (or `WriterOptions.Nullable
|
||||
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")
|
||||
// Use sqltypes package types
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "models.go",
|
||||
PackageName: "models",
|
||||
NullableTypes: writers.NullableTypeResolveSpec,
|
||||
NullableTypes: writers.NullableTypeSqlTypes,
|
||||
}
|
||||
|
||||
// Use standard library database/sql types
|
||||
@@ -184,8 +186,8 @@ options := &writers.WriterOptions{
|
||||
|
||||
- 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`, …)
|
||||
- Nullable columns use plain Go pointer types (`*string`, `*time.Time`, …) by default; pass `--types sqltypes` to use `sql_types.SqlString`, `sql_types.SqlTimeStamp`, etc., or `--types stdlib` to use `sql.NullString`, `sql.NullTime`, etc.
|
||||
- Array columns use plain Go slices (`[]string`, `[]int32`, …) by default; `--types sqltypes` uses `sql_types.SqlStringArray`, `sql_types.SqlInt32Array`, etc.
|
||||
- Multi-file mode: one file per table named `sql_{schema}_{table}.go`
|
||||
- Generated code is auto-formatted
|
||||
- JSON tags are automatically added
|
||||
|
||||
@@ -141,10 +141,10 @@ func NewModelData(table *models.Table, schema string, typeMapper *TypeMapper, fl
|
||||
safeName := writers.SanitizeStructTagValue(col.Name)
|
||||
model.PrimaryKeyField = SnakeCaseToPascalCase(safeName)
|
||||
model.IDColumnName = safeName
|
||||
// Check if PK type is a SQL type (contains resolvespec_common or sql_types)
|
||||
// Check if PK type is a SQL type (contains sql_types)
|
||||
goType := typeMapper.SQLTypeToGoType(col.Type, col.NotNull)
|
||||
model.PrimaryKeyType = goType
|
||||
model.PrimaryKeyIsSQL = strings.Contains(goType, "resolvespec_common") || strings.Contains(goType, "sql_types")
|
||||
model.PrimaryKeyIsSQL = strings.Contains(goType, "sql_types")
|
||||
model.PrimaryKeyIsStr = isStringLikePrimaryKeyType(goType)
|
||||
model.PrimaryKeyIDType = "int64"
|
||||
if model.PrimaryKeyIsStr {
|
||||
@@ -203,7 +203,7 @@ func formatComment(description, comment string) string {
|
||||
|
||||
func isStringLikePrimaryKeyType(goType string) bool {
|
||||
switch goType {
|
||||
case "string", "sql.NullString", "resolvespec_common.SqlString", "resolvespec_common.SqlUUID":
|
||||
case "string", "sql.NullString", "sql_types.SqlString", "sql_types.SqlUUID":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -12,18 +12,18 @@ import (
|
||||
// TypeMapper handles type conversions between SQL and Go types for Bun
|
||||
type TypeMapper struct {
|
||||
sqlTypesAlias string
|
||||
typeStyle string // writers.NullableTypeResolveSpec | writers.NullableTypeStdlib
|
||||
typeStyle string // writers.NullableTypeSqlTypes | writers.NullableTypeStdlib | writers.NullableTypeBaselib
|
||||
}
|
||||
|
||||
// NewTypeMapper creates a new TypeMapper.
|
||||
// typeStyle should be writers.NullableTypeResolveSpec or writers.NullableTypeStdlib;
|
||||
// an empty string defaults to resolvespec.
|
||||
// typeStyle should be writers.NullableTypeSqlTypes, writers.NullableTypeStdlib, or
|
||||
// writers.NullableTypeBaselib; an empty string defaults to baselib.
|
||||
func NewTypeMapper(typeStyle string) *TypeMapper {
|
||||
if typeStyle == "" {
|
||||
typeStyle = writers.NullableTypeBaselib
|
||||
}
|
||||
return &TypeMapper{
|
||||
sqlTypesAlias: "resolvespec_common",
|
||||
sqlTypesAlias: "sql_types",
|
||||
typeStyle: typeStyle,
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (tm *TypeMapper) SQLTypeToGoType(sqlType string, notNull bool) string {
|
||||
return tm.baselibNullableGoType(baseType)
|
||||
}
|
||||
|
||||
// resolvespec (default): use base Go types only for simple NOT NULL fields.
|
||||
// sqltypes: use base Go types only for simple NOT NULL fields.
|
||||
if notNull && tm.isSimpleType(baseType) {
|
||||
return tm.baseGoType(baseType)
|
||||
}
|
||||
@@ -106,11 +106,11 @@ func (tm *TypeMapper) baseGoType(sqlType string) string {
|
||||
return goType
|
||||
}
|
||||
|
||||
// Default to resolvespec type
|
||||
// Default to sqltypes type
|
||||
return tm.bunGoType(sqlType)
|
||||
}
|
||||
|
||||
// bunGoType returns the Bun/ResolveSpec common type
|
||||
// bunGoType returns the Bun/sqltypes common type
|
||||
func (tm *TypeMapper) bunGoType(sqlType string) string {
|
||||
typeMap := map[string]string{
|
||||
// Integer types
|
||||
@@ -461,9 +461,9 @@ func (tm *TypeMapper) NeedsFmtImport(generateGetIDStr bool) bool {
|
||||
return generateGetIDStr
|
||||
}
|
||||
|
||||
// GetSQLTypesImport returns the import path for the spectypes package.
|
||||
// GetSQLTypesImport returns the import path for the sqltypes package.
|
||||
func (tm *TypeMapper) GetSQLTypesImport() string {
|
||||
return "git.warky.dev/wdevs/relspecgo/pkg/spectypes"
|
||||
return "git.warky.dev/wdevs/relspecgo/pkg/sqltypes"
|
||||
}
|
||||
|
||||
// GetNullableTypeImportLine returns the full Go import line for the nullable type
|
||||
|
||||
@@ -80,7 +80,7 @@ func (w *Writer) writeSingleFile(db *models.Database) error {
|
||||
// Add bun import (always needed)
|
||||
templateData.AddImport(fmt.Sprintf("\"%s\"", w.typeMapper.GetBunImport()))
|
||||
|
||||
// Add nullable types import (resolvespec or stdlib depending on options)
|
||||
// Add nullable types import (sqltypes or stdlib depending on options)
|
||||
templateData.AddImport(w.typeMapper.GetNullableTypeImportLine())
|
||||
|
||||
// Collect all models
|
||||
@@ -177,7 +177,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
|
||||
// Add bun import
|
||||
templateData.AddImport(fmt.Sprintf("\"%s\"", w.typeMapper.GetBunImport()))
|
||||
|
||||
// Add nullable types import (resolvespec or stdlib depending on options)
|
||||
// Add nullable types import (sqltypes or stdlib depending on options)
|
||||
templateData.AddImport(w.typeMapper.GetNullableTypeImportLine())
|
||||
|
||||
// Create model data
|
||||
|
||||
@@ -550,7 +550,7 @@ func TestWriter_FieldNameCollision(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify NO field named just "TableName" (without underscore)
|
||||
if strings.Contains(generated, "TableName resolvespec_common") || strings.Contains(generated, "TableName string") {
|
||||
if strings.Contains(generated, "TableName sql_types") || strings.Contains(generated, "TableName string") {
|
||||
t.Errorf("Field 'TableName' without underscore should not exist (would conflict with method)\nGenerated:\n%s", generated)
|
||||
}
|
||||
}
|
||||
@@ -827,9 +827,9 @@ func TestTypeMapper_BuildBunTag(t *testing.T) {
|
||||
t.Errorf("BuildBunTag() = %q, missing %q", result, part)
|
||||
}
|
||||
}
|
||||
// resolvespec mode must NOT add "array" — SqlXxxArray uses sql.Scanner
|
||||
// sqltypes mode must NOT add "array" — SqlXxxArray uses sql.Scanner
|
||||
if strings.Contains(result, ",array,") || strings.HasSuffix(result, ",array,") {
|
||||
t.Errorf("BuildBunTag() = %q, must not contain 'array' in resolvespec mode", result)
|
||||
t.Errorf("BuildBunTag() = %q, must not contain 'array' in sqltypes mode", result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ Generates Go source files with GORM model definitions from database schema infor
|
||||
|
||||
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.
|
||||
|
||||
With `--types sqltypes`, nullable fields use the [`pkg/sqltypes`](../../sqltypes/README.md) package.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates GORM-compatible Go structs
|
||||
@@ -48,19 +50,19 @@ func main() {
|
||||
### CLI Examples
|
||||
|
||||
```bash
|
||||
# Generate GORM models from a DBML schema (default: resolvespec types)
|
||||
# Generate GORM models from a DBML schema (default: baselib pointer 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
|
||||
# Use standard library database/sql nullable types instead
|
||||
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)
|
||||
# Select sqltypes package types (git.warky.dev/wdevs/relspecgo/pkg/sqltypes)
|
||||
relspec convert --from pgsql --from-conn "postgres://localhost/mydb" \
|
||||
--to gorm --to-path models.go --package models \
|
||||
--types resolvespec
|
||||
--types sqltypes
|
||||
|
||||
# Multi-file output (one file per table)
|
||||
relspec convert --from json --from-path schema.json \
|
||||
@@ -89,13 +91,13 @@ Files are named: `sql_{schema}_{table}.go`
|
||||
|
||||
## Generated Code Examples
|
||||
|
||||
### Default — resolvespec types (`--types resolvespec`)
|
||||
### sqltypes package types (`--types sqltypes`)
|
||||
|
||||
```go
|
||||
package models
|
||||
|
||||
import (
|
||||
sql_types "github.com/bitechdev/ResolveSpec/pkg/spectypes"
|
||||
sql_types "git.warky.dev/wdevs/relspecgo/pkg/sqltypes"
|
||||
)
|
||||
|
||||
type ModelUser struct {
|
||||
@@ -141,11 +143,11 @@ func (ModelUser) TableName() string {
|
||||
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")
|
||||
// Use sqltypes package types
|
||||
options := &writers.WriterOptions{
|
||||
OutputPath: "models.go",
|
||||
PackageName: "models",
|
||||
NullableTypes: writers.NullableTypeResolveSpec,
|
||||
NullableTypes: writers.NullableTypeSqlTypes,
|
||||
}
|
||||
|
||||
// Use standard library database/sql types
|
||||
@@ -176,7 +178,7 @@ options := &writers.WriterOptions{
|
||||
|
||||
The nullable type package is selected with `--types` (or `WriterOptions.NullableTypes`).
|
||||
|
||||
| SQL Type | NOT NULL — both | Nullable — resolvespec | Nullable — stdlib |
|
||||
| SQL Type | NOT NULL — both | Nullable — sqltypes | Nullable — stdlib |
|
||||
|---|---|---|---|
|
||||
| `bigint` | `int64` | `SqlInt64` | `sql.NullInt64` |
|
||||
| `integer` | `int32` | `SqlInt32` | `sql.NullInt32` |
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
// TypeMapper handles type conversions between SQL and Go types
|
||||
type TypeMapper struct {
|
||||
sqlTypesAlias string
|
||||
typeStyle string // writers.NullableTypeResolveSpec | writers.NullableTypeStdlib
|
||||
typeStyle string // writers.NullableTypeSqlTypes | writers.NullableTypeStdlib | writers.NullableTypeBaselib
|
||||
}
|
||||
|
||||
// NewTypeMapper creates a new TypeMapper.
|
||||
// typeStyle should be writers.NullableTypeResolveSpec or writers.NullableTypeStdlib;
|
||||
// an empty string defaults to resolvespec.
|
||||
// typeStyle should be writers.NullableTypeSqlTypes, writers.NullableTypeStdlib, or
|
||||
// writers.NullableTypeBaselib; an empty string defaults to baselib.
|
||||
func NewTypeMapper(typeStyle string) *TypeMapper {
|
||||
if typeStyle == "" {
|
||||
typeStyle = writers.NullableTypeBaselib
|
||||
@@ -50,7 +50,7 @@ func (tm *TypeMapper) SQLTypeToGoType(sqlType string, notNull bool) string {
|
||||
return tm.baselibNullableGoType(baseType)
|
||||
}
|
||||
|
||||
// resolvespec (default)
|
||||
// sqltypes
|
||||
if notNull {
|
||||
return tm.baseGoType(baseType)
|
||||
}
|
||||
@@ -505,9 +505,9 @@ func (tm *TypeMapper) NeedsFmtImport(generateGetIDStr bool) bool {
|
||||
return generateGetIDStr
|
||||
}
|
||||
|
||||
// GetSQLTypesImport returns the import path for the spectypes package.
|
||||
// GetSQLTypesImport returns the import path for the sqltypes package.
|
||||
func (tm *TypeMapper) GetSQLTypesImport() string {
|
||||
return "git.warky.dev/wdevs/relspecgo/pkg/spectypes"
|
||||
return "git.warky.dev/wdevs/relspecgo/pkg/sqltypes"
|
||||
}
|
||||
|
||||
// GetNullableTypeImportLine returns the full Go import line for the nullable type
|
||||
|
||||
@@ -77,7 +77,7 @@ func (w *Writer) writeSingleFile(db *models.Database) error {
|
||||
packageName := w.getPackageName()
|
||||
templateData := NewTemplateData(packageName, w.config)
|
||||
|
||||
// Add nullable types import (resolvespec or stdlib depending on options)
|
||||
// Add nullable types import (sqltypes or stdlib depending on options)
|
||||
templateData.AddImport(w.typeMapper.GetNullableTypeImportLine())
|
||||
|
||||
// Collect all models
|
||||
@@ -171,7 +171,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
|
||||
// Create template data for this single table
|
||||
templateData := NewTemplateData(packageName, w.config)
|
||||
|
||||
// Add nullable types import (resolvespec or stdlib depending on options)
|
||||
// Add nullable types import (sqltypes or stdlib depending on options)
|
||||
templateData.AddImport(w.typeMapper.GetNullableTypeImportLine())
|
||||
|
||||
// Create model data
|
||||
|
||||
@@ -23,9 +23,9 @@ type Writer interface {
|
||||
// NullableType constants control which Go package is used for nullable column types
|
||||
// in code-generation writers (Bun, GORM).
|
||||
const (
|
||||
// NullableTypeResolveSpec uses git.warky.dev/wdevs/relspecgo/pkg/spectypes
|
||||
// NullableTypeSqlTypes uses git.warky.dev/wdevs/relspecgo/pkg/sqltypes
|
||||
// (SqlString, SqlInt32, SqlVector, SqlStringArray, …).
|
||||
NullableTypeResolveSpec = "resolvespec"
|
||||
NullableTypeSqlTypes = "sqltypes"
|
||||
|
||||
// NullableTypeStdlib uses the standard library database/sql nullable types
|
||||
// (sql.NullString, sql.NullInt32, …) and plain Go slices for arrays.
|
||||
@@ -52,9 +52,9 @@ type WriterOptions struct {
|
||||
|
||||
// NullableTypes selects the Go type package used for nullable columns in
|
||||
// code-generation writers (bun, gorm). Accepted values:
|
||||
// "resolvespec" (default) — git.warky.dev/wdevs/relspecgo/pkg/spectypes
|
||||
// "sqltypes" — git.warky.dev/wdevs/relspecgo/pkg/sqltypes
|
||||
// "stdlib" — database/sql (sql.NullString, sql.NullInt32, …)
|
||||
// "baselib" — plain Go pointer types (*string, *int32, …)
|
||||
// "baselib" (default) — plain Go pointer types (*string, *int32, …)
|
||||
NullableTypes string
|
||||
|
||||
// Prisma7 enables Prisma 7-specific output for Prisma writers.
|
||||
|
||||
Reference in New Issue
Block a user