Skip to content

dan-sherwin/gormdb2struct

Repository files navigation

gormdb2struct

gormdb2struct is a schema-first code generator for Go + GORM that emits typed gorm.io/gen query code.

It connects to an existing PostgreSQL or SQLite database and generates:

  • GORM model structs
  • typed gorm.io/gen query helpers
  • an optional DbInit file for the chosen dialect
  • optional PostgreSQL wrapper types for enums, domains, and enum arrays

If your database schema is the source of truth and you are tired of hand-maintaining structs, gorm.io/gen query scaffolding, and custom type plumbing, this tool is built for that workflow.

Why This Exists

Many Go teams using GORM still end up doing a lot of repetitive work by hand:

  • rebuilding model structs every time the schema changes
  • writing boilerplate around PostgreSQL enums and domains
  • keeping generated query code and manual model code in sync
  • stitching database-specific initialization code into each project

gormdb2struct exists to take that work off the critical path without introducing hidden state or a heavyweight framework.

Best Fit

This tool is a strong fit if you:

  • already have a PostgreSQL or SQLite schema
  • use GORM and want typed query helpers from gorm.io/gen
  • want a config-first CLI that works well in CI/CD
  • have PostgreSQL enums, domains, arrays, or custom wrapper types that need to stay honest

It is especially useful for PostgreSQL-heavy codebases where enums and domains are part of the real application contract, not just database decoration.

Highlights

  • PostgreSQL and SQLite support today
  • Typed query generation via gorm.io/gen
  • Versioned, human-editable TOML configuration
  • Optional DbInit generation with app-settings and slog-gorm support
  • Unified TypeMap for standard types, enums, domains, and arrays
  • PostgreSQL generated wrapper types for enums, domains, and enum arrays
  • PostgreSQL inspection commands that recommend missing mappings and can emit a starter config
  • Support for importing existing Go type packages so the inspector can recommend real TypeMap entries instead of generated wrappers
  • Built-in pgtypes package for PostgreSQL arrays and intervals
  • Stateless CLI design with no persistent local settings

Install

Homebrew

brew tap dan-sherwin/homebrew-tap
brew install gormdb2struct

Or:

brew install dan-sherwin/homebrew-tap/gormdb2struct

Binary release

Download the latest archive from the Releases page, extract it, and place gormdb2struct somewhere on your PATH.

DNF / YUM

sudo dnf config-manager --add-repo https://dan-sherwin.github.io/dan-sherwin.repo
sudo dnf install gormdb2struct

On older yum-based systems, install the repo-management package first if needed.

Build from source

Requires Go 1.26+.

git clone https://github.com/dan-sherwin/gormdb2struct.git
cd gormdb2struct
go build -o gormdb2struct ./cmd
./gormdb2struct --help

Quick Start

Generate a starter config:

gormdb2struct generate-config-sample

If you are working against PostgreSQL and want help discovering enums, domains, and custom types before you write a config by hand:

gormdb2struct inspect-postgresql \
  --host localhost \
  --database my_database \
  --user my_user \
  --password-env DB_PASSWORD \
  -o starter.toml

If you already know you want to reuse types from an existing Go package, include it:

gormdb2struct inspect-postgresql \
  --host localhost \
  --database my_database \
  --user my_user \
  --password-env DB_PASSWORD \
  --import-package go.corp.spacelink.com/sdks/go/sl_datatypes \
  -o starter.toml

Then generate the code:

gormdb2struct ./starter.toml

For a full self-contained walkthrough you can run locally, see examples/sqlite-quickstart.

If you already have a config and just want a recommendation pass over the objects it references:

gormdb2struct inspect ./gormdb2struct.toml

For a paste-ready TOML recommendation snippet from an existing config:

gormdb2struct inspect ./gormdb2struct.toml --format toml

What Makes It Different

The differentiator is not just model generation. It is the PostgreSQL type story.

gormdb2struct can help with cases like:

  • PostgreSQL enums that should become real Go enum wrapper types
  • PostgreSQL domains that should map to existing application types
  • enum arrays that need a real wrapper type instead of a raw slice
  • projects that already have packages like sl_datatypes and want those reused automatically in generated config recommendations

That means you can mix and match:

  • generated wrappers for schema-defined enums and domains
  • explicit TypeMap entries for hand-written domain types you already trust
  • default built-in support from pgtypes for common PostgreSQL arrays and intervals

Commands

gormdb2struct supports four main entry points:

  • gormdb2struct <config.toml> Generate code from a config file.
  • gormdb2struct generate-config-sample Write a full commented starter config.
  • gormdb2struct inspect <config.toml> Inspect the PostgreSQL objects referenced by an existing config and recommend type mappings.
  • gormdb2struct inspect-postgresql Connect directly to PostgreSQL from CLI flags, print an inspection report, and optionally emit a starter config.

inspect-postgresql password input options:

  • --password
  • --password-env
  • --password-stdin
  • --password-prompt

If -o/--out is omitted, inspect-postgresql prints only the human-readable inspection report.

If -o stdout is used, it prints the starter TOML after the report.

If -o <path> is used, it writes only the starter TOML to that file.

Configuration

The preferred config format is explicit and versioned:

ConfigVersion = 1

If ConfigVersion is omitted, gormdb2struct falls back to a legacy compatibility parser for older shipped configs.

Main sections in the versioned format:

  • [Generator]
  • [Database]
  • [Database.PostgreSQL]
  • [Database.SQLite]
  • [DbInit]
  • [TypeMap]
  • [ExtraFields]
  • [JSONTagOverridesByTable]
  • [PostgreSQL.GeneratedTypes]
  • [PostgreSQL.GeneratedTypes.TypeMap]

Use gormdb2struct generate-config-sample for the full commented example. The sample is structured for hand editing and grouped so dialect-specific settings are easy to find.

Minimal PostgreSQL example:

ConfigVersion = 1

[Generator]
OutPath = "./generated"
Objects = ["tickets", "ticket_extended"]
ImportPackagePaths = ["github.com/dan-sherwin/gormdb2struct/pgtypes"]

[Database]
Dialect = "postgresql"

[Database.PostgreSQL]
Host = "localhost"
Port = 5432
Name = "ticket_data_core"
User = "ticket_service"
Password = "secret"
SSLMode = false

[DbInit]
Enabled = true
IncludeAutoMigrate = false

[TypeMap]
"spacelink_identifier" = "sl_datatypes.SpacelinkIdentifier"

[PostgreSQL.GeneratedTypes]
PackageName = "types"
RelativePath = "models/types"

[PostgreSQL.GeneratedTypes.TypeMap]
"ticket_status" = "TicketStatus"
"ticket_type" = "TicketType"

Validation highlights:

  • [Generator].OutPath is required
  • [Database].Dialect must be postgresql or sqlite
  • PostgreSQL requires host and database name
  • SQLite requires a database file path
  • PostgreSQL generated types are only available when the dialect is PostgreSQL

Generated Output

Given OutPath = "./generated":

  • ./generated/models Generated model structs with gorm and json tags
  • ./generated gorm.io/gen query helpers and optional db.go / db_sqlite.go
  • ./generated/models/dbtypes or your configured generated-types path PostgreSQL wrapper types when PostgreSQL.GeneratedTypes is enabled

If OutPackagePath is omitted, gormdb2struct will try to derive it from the current Go module when it needs to emit importable generated files like DbInit.

Generated DbInit

DbInit generation is optional and controlled by the [DbInit] section.

When enabled, generated init code can:

  • open the database connection for the selected dialect
  • register default query objects
  • optionally run AutoMigrate
  • optionally register database settings with github.com/dan-sherwin/go-app-settings
  • optionally use github.com/orandin/slog-gorm as the GORM logger

DbInit returns an error instead of panicking or exiting, so the parent application stays in control.

PostgreSQL pgtypes

The repo also ships a reusable pgtypes package for PostgreSQL array and interval handling.

It includes support for types like:

  • pgtypes.StringArray
  • pgtypes.BoolArray
  • pgtypes.Int32Array
  • pgtypes.Int64Array
  • pgtypes.Float64Array
  • pgtypes.UUIDArray
  • pgtypes.TimeArray
  • pgtypes.Duration
  • pgtypes.DurationArray

This package is useful even outside the generator if you want GORM-friendly wrappers for PostgreSQL array and interval columns.

Architecture

  • cmd/main.go Single executable entrypoint
  • cmd/app CLI parsing, top-level command dispatch, logging, and version/build metadata
  • internal/config Config loading, normalization, validation, and sample generation
  • internal/generator Schema inspection, generation orchestration, dialect handling, and emitted-file logic
  • pgtypes Public PostgreSQL helper types for generated projects

The tool is intentionally stateless. There are no persistent settings and no hidden local project database.

Development

The local quality gate lives at:

./dev/ci-local.sh

That script runs formatting checks, build, vet, tests, lint, and govulncheck.

Roadmap

Current support is focused on PostgreSQL and SQLite.

Additional GORM dialects are planned for future releases, with likely expansion in this order:

  • MySQL
  • TiDB
  • GaussDB
  • SQL Server
  • ClickHouse
  • Oracle

The long-term goal is not just more dialectors, but dialect-specific generation that stays honest about what each database can actually support.

Contributing

Issues and pull requests are welcome. Clear reproduction steps, config samples, and tests are especially helpful.

License

This project is licensed under the terms of the LICENSE file in this repository.

About

Generate GORM models, typed gorm.io/gen query helpers, and PostgreSQL wrapper types from an existing schema.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors