https://github.com/m4gshm/fieldr
Boilerplate code killer. Generates various code, such as getters/setters, builders, or constants.
https://github.com/m4gshm/fieldr
boilerplate builder code-generation code-generator codegen constants enum fields getter go golang orm setter stringify
Last synced: 3 months ago
JSON representation
Boilerplate code killer. Generates various code, such as getters/setters, builders, or constants.
- Host: GitHub
- URL: https://github.com/m4gshm/fieldr
- Owner: m4gshm
- License: mit
- Created: 2021-09-07T20:38:29.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2025-10-04T23:52:24.000Z (6 months ago)
- Last Synced: 2025-10-05T01:17:47.964Z (6 months ago)
- Topics: boilerplate, builder, code-generation, code-generator, codegen, constants, enum, fields, getter, go, golang, orm, setter, stringify
- Language: Go
- Homepage:
- Size: 549 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Fieldr
Generator of various enumerated constants, types, functions based on a
type properties like name, structure fields, tags or base type nature.
## Supported commands
- [fields-to-consts](#fields-to-consts-example) - generate constants
based on template applied to struct fields.
- [get-set](#get-set-usage-example) - generates getters and setters.
- [new-opt](#functional-options-constructor-example) - generates a
function that creates an optionally initialized struct instance.
- [new-full](#full-constructor-example) - generates a function that
creates a full initialized struct instance.
- [builder](#builder-usage-example) - generates builder API of a struct
type.
- [as-map](#as-map-usage-example) - generates a method or functon that
converts a struct to a map.
- [enrich-const-type](#enrich-const-type-usage-example) - extends a
constants type by 'get name' method, 'enum all values' function and
'get a constant by a value of the underlying type' function.
## Installation
``` console
go install github.com/m4gshm/fieldr@latest
```
or
``` console
go install github.com/m4gshm/fieldr@HEAD
```
## fields-to-consts example
source `entity.go`:
``` go
package enum_const
//go:generate fieldr -type Entity fields-to-consts -val tag.json -list jsons
type Entity struct {
Id int `json:"id"`
Name string `json:"name"`
}
```
then running this command in the same directory:
``` console
go generate .
```
will be generated `entity_fieldr.go` file with the next content:
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package enum_const
const (
entityJsonId = "id"
entityJsonName = "name"
)
func jsons() []string {
return []string{entityJsonId, entityJsonName}
}
```
this consist of constants based on the `json` tag contents and the
method `jsons` that enumerates these constants.
To get extended help of the command, use the following:
``` console
fieldr fields-to-consts help
```
### Example of generating ORM elements:
source `entity.go`:
``` go
package enum_const_db
//go:generate fieldr -type Entity
//go:fieldr fields-to-consts -name "'col' + field.name" -val "tag.db" -flat Versioned -type column -list . -ref-access .
//go:fieldr fields-to-consts -name "'pk' + field.name" -val "tag.db" -include "tag.pk == 'true'" -type column -list pk
type Entity struct {
BaseEntity
Versioned *VersionedEntity
Name string `db:"name"`
}
type BaseEntity struct {
ID int32 `db:"id" pk:"true"`
}
type VersionedEntity struct {
Version int64 `db:"version"`
}
```
generated `entity_fieldr.go`:
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package enum_const_db
type column string
const (
colID column = "id"
colVersion column = "version"
colName column = "name"
pkID column = "id"
)
func columns() []column {
return []column{colID, colVersion, colName}
}
func (s *Entity) ref(f column) any {
if s == nil {
return nil
}
switch f {
case colID:
return &s.BaseEntity.ID
case colVersion:
if v := s.Versioned; v != nil {
return &v.Version
}
case colName:
return &s.Name
}
return nil
}
func pk() []column {
return []column{pkID}
}
```
#### explanation of used args:
- -name *"'col' + field.name"* - defines constant names as 'col'
appended by the associated field name.
- -val *"tag.db"* - defines the value of a constant as a copy of the
`db` tag of the associated field name.
- -flat *Versioned* - also uses the `VersionedEntity` fields as
constants source type in addition to the base `Entity` type.
- -type *column* - adds the `column` type, and uses it as the type of
the generated constants.
- -list *.* - generates the `columns` function that returns constant
values. It can be used to build sql queries like INSERT, SELECT.
- -ref-access *.* - generates the `ref` method that provides access to
the filed values, returns a reference pointing to the field associated
with the constant. The method can be used in conjunction with Row.Scan
from sql package.
- -include *"tag.pk != nil"* - uses only 'pk' tag having a value.
## get-set usage example
source `entity.go`
``` go
package get_set
import "time"
//go:generate fieldr -type Entity get-set
type BaseEntity[ID any] struct {
id ID
}
type Entity[ID any] struct {
*BaseEntity[ID]
name string
surname string
ts time.Time
}
```
``` console
go generate .
```
generates `entity_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package get_set
import "time"
func (e *Entity[ID]) ID() ID {
if e != nil {
if be := e.BaseEntity; be != nil {
return be.id
}
}
var no ID
return no
}
func (e *Entity[ID]) SetID(id ID) {
if e != nil {
if be := e.BaseEntity; be != nil {
be.id = id
}
}
}
func (e *Entity[ID]) Name() string {
if e != nil {
return e.name
}
var no string
return no
}
func (e *Entity[ID]) SetName(name string) {
if e != nil {
e.name = name
}
}
func (e *Entity[ID]) Surname() string {
if e != nil {
return e.surname
}
var no string
return no
}
func (e *Entity[ID]) SetSurname(surname string) {
if e != nil {
e.surname = surname
}
}
func (e *Entity[ID]) Ts() time.Time {
if e != nil {
return e.ts
}
var no time.Time
return no
}
func (e *Entity[ID]) SetTs(ts time.Time) {
if e != nil {
e.ts = ts
}
}
```
## 'Functional Options' constructor example
source `entity.go`
``` go
package new_opt
//go:generate fieldr -type Entity new-opt -flat -required ID
type Entity[ID any] struct {
*Model[ID]
Name string
}
type Model[ID any] struct {
ID ID
CreatedAt int64
UpdatedAt int64
}
```
``` console
go generate .
```
generates `entity_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package new_opt
func NewEntity[ID any](
id ID,
opts ...func(*Entity[ID]),
) *Entity[ID] {
r := &Entity[ID]{
Model: &Model[ID]{
ID: id,
},
}
for _, opt := range opts {
opt(r)
}
return r
}
func WithCreatedAt[ID any](createdAt int64) func(e *Entity[ID]) {
return func(e *Entity[ID]) {
m := e.Model
if m == nil {
m = new(Model[ID])
e.Model = m
}
m.CreatedAt = createdAt
}
}
func WithUpdatedAt[ID any](updatedAt int64) func(e *Entity[ID]) {
return func(e *Entity[ID]) {
m := e.Model
if m == nil {
m = new(Model[ID])
e.Model = m
}
m.UpdatedAt = updatedAt
}
}
func WithName[ID any](name string) func(e *Entity[ID]) {
return func(e *Entity[ID]) {
e.Name = name
}
}
```
## Full constructor example
source `entity.go`
``` go
package new_full
//go:generate fieldr -type Entity new-full
type Entity[ID any] struct {
*Model[ID]
Name string
}
type Model[ID any] struct {
ID ID
CreatedAt int64
UpdatedAt int64
}
```
``` console
go generate .
```
generates `entity_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package new_full
func NewEntity[ID any](
model *Model[ID],
name string,
) *Entity[ID] {
return &Entity[ID]{
Model: model,
Name: name,
}
}
```
## builder usage example
source `entity.go`
``` go
package builder
//go:generate fieldr -type Entity builder -deconstructor .
type Entity[ID any] struct {
*Model[ID]
Name string
}
type Model[ID any] struct {
ID ID
CreatedAt int64
UpdatedAt int64
}
```
``` console
go generate .
```
generates `entity_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package builder
type EntityBuilder[ID any] struct {
id ID
createdAt int64
updatedAt int64
name string
}
func NewEntityBuilder[ID any]() *EntityBuilder[ID] {
return &EntityBuilder[ID]{}
}
func (b *EntityBuilder[ID]) Build() *Entity[ID] {
if b == nil {
return &Entity[ID]{}
}
return &Entity[ID]{
Model: &Model[ID]{
ID: b.id,
CreatedAt: b.createdAt,
UpdatedAt: b.updatedAt,
},
Name: b.name,
}
}
func (b *EntityBuilder[ID]) ID(id ID) *EntityBuilder[ID] {
if b != nil {
b.id = id
}
return b
}
func (b *EntityBuilder[ID]) CreatedAt(createdAt int64) *EntityBuilder[ID] {
if b != nil {
b.createdAt = createdAt
}
return b
}
func (b *EntityBuilder[ID]) UpdatedAt(updatedAt int64) *EntityBuilder[ID] {
if b != nil {
b.updatedAt = updatedAt
}
return b
}
func (b *EntityBuilder[ID]) Name(name string) *EntityBuilder[ID] {
if b != nil {
b.name = name
}
return b
}
func (e *Entity[ID]) ToBuilder() *EntityBuilder[ID] {
if e == nil {
return &EntityBuilder[ID]{}
}
var (
e_Model_ID ID
e_Model_CreatedAt int64
e_Model_UpdatedAt int64
)
if m := e.Model; m != nil {
e_Model_ID = m.ID
e_Model_CreatedAt = m.CreatedAt
e_Model_UpdatedAt = m.UpdatedAt
}
return &EntityBuilder[ID]{
id: e_Model_ID,
createdAt: e_Model_CreatedAt,
updatedAt: e_Model_UpdatedAt,
name: e.Name,
}
}
```
## as-map usage example
source `struct.go`
``` go
package asmap
import "time"
//go:generate fieldr -type EmbeddedAddress -out address_as_map.go as-map -key-type . -export
//go:generate fieldr -type Struct -out struct_as_map.go as-map -key-type . -export -rewrite type:*EmbeddedAddress:fmt=%v.AsMap() -flat Flat
type BaseStruct struct {
ID int
TS *time.Time
}
type EmbeddedAddress struct {
ZipCode int
AddressLine string
}
type FlatPart struct {
CardNum string
Bank string
}
type Struct[n string] struct {
*BaseStruct
Name n
Surname string
noExport string //nolint
NoTag string
Address *EmbeddedAddress
Flat FlatPart
}
```
``` console
go generate .
```
generates two files `struct_as_map.go`, `address_as_map.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package asmap
type StructField string
const (
BaseStructID StructField = "ID"
BaseStructTS StructField = "TS"
Name StructField = "Name"
Surname StructField = "Surname"
NoTag StructField = "NoTag"
Address StructField = "Address"
FlatCardNum StructField = "CardNum"
FlatBank StructField = "Bank"
)
func (s *Struct[n]) AsMap() map[StructField]any {
if s == nil {
return nil
}
m := map[StructField]any{}
if bs := s.BaseStruct; bs != nil {
m[BaseStructID] = bs.ID
}
if bs := s.BaseStruct; bs != nil {
if ts := bs.TS; ts != nil {
m[BaseStructTS] = ts
}
}
m[Name] = s.Name
m[Surname] = s.Surname
m[NoTag] = s.NoTag
if a := s.Address; a != nil {
m[Address] = a.AsMap()
}
m[FlatCardNum] = s.Flat.CardNum
m[FlatBank] = s.Flat.Bank
return m
}
```
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package asmap
type EmbeddedAddressField string
const (
ZipCode EmbeddedAddressField = "ZipCode"
AddressLine EmbeddedAddressField = "AddressLine"
)
func (e *EmbeddedAddress) AsMap() map[EmbeddedAddressField]any {
if e == nil {
return nil
}
m := map[EmbeddedAddressField]any{}
m[ZipCode] = e.ZipCode
m[AddressLine] = e.AddressLine
return m
}
```
## enrich-const-type usage example
source `enum.go`
``` go
package enrich_enum
//go:generate fieldr -type Enum enrich-const-type -export
type Enum int
const (
AA Enum = iota + 1
BB
CC
DD
)
//go:generate fieldr -type StringEnum enrich-const-type -export
type BaseStringEnum string
type StringEnum BaseStringEnum
const (
FIRST StringEnum = "first one"
SECOND StringEnum = "one more"
THIRD StringEnum = "any third"
)
```
``` console
go generate .
```
generates `enum_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package enrich_enum
func (e Enum) Name() string {
switch e {
case AA:
return "AA"
case BB:
return "BB"
case CC:
return "CC"
case DD:
return "DD"
default:
return ""
}
}
func EnumAll() []Enum {
return []Enum{
AA,
BB,
CC,
DD,
}
}
func EnumByName(name string) (e Enum, ok bool) {
ok = true
switch name {
case "AA":
e = AA
case "BB":
e = BB
case "CC":
e = CC
case "DD":
e = DD
default:
ok = false
}
return
}
func EnumByValue(value int) (e Enum, ok bool) {
ok = true
switch value {
case 1:
e = AA
case 2:
e = BB
case 3:
e = CC
case 4:
e = DD
default:
ok = false
}
return
}
```
and `enum_string_enum_fieldr.go`
``` go
// Code generated by 'fieldr'; DO NOT EDIT.
package enrich_enum
func (s StringEnum) Name() string {
switch s {
case FIRST:
return "FIRST"
case SECOND:
return "SECOND"
case THIRD:
return "THIRD"
default:
return ""
}
}
func StringEnumAll() []StringEnum {
return []StringEnum{
FIRST,
SECOND,
THIRD,
}
}
func StringEnumByName(name string) (e StringEnum, ok bool) {
ok = true
switch name {
case "FIRST":
e = FIRST
case "SECOND":
e = SECOND
case "THIRD":
e = THIRD
default:
ok = false
}
return
}
func StringEnumByValue(value string) (e StringEnum, ok bool) {
ok = true
switch value {
case "first one":
e = FIRST
case "one more":
e = SECOND
case "any third":
e = THIRD
default:
ok = false
}
return
}
```
See more examples [here](./internal/examples/)