fix camelize generated fields

This commit is contained in:
Nimer Farahty 2025-06-09 03:03:33 +03:00
parent b0120532af
commit 8f649f2a59
8 changed files with 239 additions and 20 deletions

View File

@ -7,6 +7,7 @@ import (
"os"
"strings"
"git.farahty.com/nimer/go-mongo/utils"
"github.com/99designs/gqlgen/api"
"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/plugin/modelgen"
@ -29,7 +30,7 @@ func mutateHook(b *modelgen.ModelBuild) *modelgen.ModelBuild {
field.Tag = strings.TrimSuffix(field.Tag, `"`) + `,omitempty" bson:"-"`
}
} else {
field.Tag = strings.TrimSuffix(field.Tag, `"`) + `" bson:"` + strings.ToLower(field.Name) + `,omitempty"`
field.Tag = strings.TrimSuffix(field.Tag, `"`) + `" bson:"` + utils.Camelize(field.Name) + `,omitempty"`
}
}
}

View File

@ -58,6 +58,7 @@ type DirectiveRoot struct {
type ComplexityRoot struct {
Category struct {
Body func(childComplexity int) int
Children func(childComplexity int) int
CreatedAt func(childComplexity int) int
CreatedBy func(childComplexity int) int
CreatedByID func(childComplexity int) int
@ -130,6 +131,8 @@ type ComplexityRoot struct {
type CategoryResolver interface {
Parent(ctx context.Context, obj *models.Category) (*models.Category, error)
Children(ctx context.Context, obj *models.Category) ([]*models.Category, error)
CreatedBy(ctx context.Context, obj *models.Category) (*models.User, error)
UpdatedBy(ctx context.Context, obj *models.Category) (*models.User, error)
@ -189,6 +192,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Category.Body(childComplexity), true
case "Category.children":
if e.complexity.Category.Children == nil {
break
}
return e.complexity.Category.Children(childComplexity), true
case "Category.createdAt":
if e.complexity.Category.CreatedAt == nil {
break
@ -752,6 +762,9 @@ input TranslatedInput {
parent: Category @goField(forceResolver: true)
parentId: ID
"#bson:ignore"
children: [Category] @goField(forceResolver: true)
createdAt: Time!
updatedAt: Time!
@ -1389,6 +1402,8 @@ func (ec *executionContext) fieldContext_Category_parent(_ context.Context, fiel
return ec.fieldContext_Category_parent(ctx, field)
case "parentId":
return ec.fieldContext_Category_parentId(ctx, field)
case "children":
return ec.fieldContext_Category_children(ctx, field)
case "createdAt":
return ec.fieldContext_Category_createdAt(ctx, field)
case "updatedAt":
@ -1453,6 +1468,77 @@ func (ec *executionContext) fieldContext_Category_parentId(_ context.Context, fi
return fc, nil
}
func (ec *executionContext) _Category_children(ctx context.Context, field graphql.CollectedField, obj *models.Category) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Category_children(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Category().Children(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.([]*models.Category)
fc.Result = res
return ec.marshalOCategory2ᚕᚖgitᚗfarahtyᚗcomᚋnimerᚋgoᚑmongoᚋmodelsᚐCategory(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Category_children(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Category",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_Category_id(ctx, field)
case "title":
return ec.fieldContext_Category_title(ctx, field)
case "body":
return ec.fieldContext_Category_body(ctx, field)
case "parent":
return ec.fieldContext_Category_parent(ctx, field)
case "parentId":
return ec.fieldContext_Category_parentId(ctx, field)
case "children":
return ec.fieldContext_Category_children(ctx, field)
case "createdAt":
return ec.fieldContext_Category_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_Category_updatedAt(ctx, field)
case "createdBy":
return ec.fieldContext_Category_createdBy(ctx, field)
case "createdById":
return ec.fieldContext_Category_createdById(ctx, field)
case "updatedBy":
return ec.fieldContext_Category_updatedBy(ctx, field)
case "updatedById":
return ec.fieldContext_Category_updatedById(ctx, field)
case "owner":
return ec.fieldContext_Category_owner(ctx, field)
case "ownerId":
return ec.fieldContext_Category_ownerId(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Category", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _Category_createdAt(ctx context.Context, field graphql.CollectedField, obj *models.Category) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Category_createdAt(ctx, field)
if err != nil {
@ -2102,6 +2188,8 @@ func (ec *executionContext) fieldContext_Mutation_createCategory(ctx context.Con
return ec.fieldContext_Category_parent(ctx, field)
case "parentId":
return ec.fieldContext_Category_parentId(ctx, field)
case "children":
return ec.fieldContext_Category_children(ctx, field)
case "createdAt":
return ec.fieldContext_Category_createdAt(ctx, field)
case "updatedAt":
@ -2327,6 +2415,8 @@ func (ec *executionContext) fieldContext_Query_categories(_ context.Context, fie
return ec.fieldContext_Category_parent(ctx, field)
case "parentId":
return ec.fieldContext_Category_parentId(ctx, field)
case "children":
return ec.fieldContext_Category_children(ctx, field)
case "createdAt":
return ec.fieldContext_Category_createdAt(ctx, field)
case "updatedAt":
@ -2399,6 +2489,8 @@ func (ec *executionContext) fieldContext_Query_category(ctx context.Context, fie
return ec.fieldContext_Category_parent(ctx, field)
case "parentId":
return ec.fieldContext_Category_parentId(ctx, field)
case "children":
return ec.fieldContext_Category_children(ctx, field)
case "createdAt":
return ec.fieldContext_Category_createdAt(ctx, field)
case "updatedAt":
@ -5979,6 +6071,39 @@ func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet,
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "parentId":
out.Values[i] = ec._Category_parentId(ctx, field, obj)
case "children":
field := field
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._Category_children(ctx, field, obj)
return res
}
if field.Deferrable != nil {
dfs, ok := deferred[field.Deferrable.Label]
di := 0
if ok {
dfs.AddField(field)
di = len(dfs.Values) - 1
} else {
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
deferred[field.Deferrable.Label] = dfs
}
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
return innerFunc(ctx, dfs)
})
// don't run the out.Concurrently() call below
out.Values[i] = graphql.Null
continue
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "createdAt":
out.Values[i] = ec._Category_createdAt(ctx, field, obj)
if out.Values[i] == graphql.Null {
@ -7584,6 +7709,47 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
return res
}
func (ec *executionContext) marshalOCategory2ᚕᚖgitᚗfarahtyᚗcomᚋnimerᚋgoᚑmongoᚋmodelsᚐCategory(ctx context.Context, sel ast.SelectionSet, v []*models.Category) graphql.Marshaler {
if v == nil {
return graphql.Null
}
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
isLen1 := len(v) == 1
if !isLen1 {
wg.Add(len(v))
}
for i := range v {
i := i
fc := &graphql.FieldContext{
Index: &i,
Result: &v[i],
}
ctx := graphql.WithFieldContext(ctx, fc)
f := func(i int) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
if !isLen1 {
defer wg.Done()
}
ret[i] = ec.marshalOCategory2ᚖgitᚗfarahtyᚗcomᚋnimerᚋgoᚑmongoᚋmodelsᚐCategory(ctx, sel, v[i])
}
if isLen1 {
f(i)
} else {
go f(i)
}
}
wg.Wait()
return ret
}
func (ec *executionContext) marshalOCategory2ᚖgitᚗfarahtyᚗcomᚋnimerᚋgoᚑmongoᚋmodelsᚐCategory(ctx context.Context, sel ast.SelectionSet, v *models.Category) graphql.Marshaler {
if v == nil {
return graphql.Null

View File

@ -8,6 +8,9 @@ type Category implements Base {
parent: Category @goField(forceResolver: true)
parentId: ID
"#bson:ignore"
children: [Category] @goField(forceResolver: true)
createdAt: Time!
updatedAt: Time!

View File

@ -27,19 +27,21 @@ type Category struct {
Title []*Translated `json:"title" bson:"title,omitempty"`
Body []*Translated `json:"body,omitempty" bson:"body,omitempty"`
// #bson:ignore
Parent *Category `json:"parent,omitempty,omitempty" bson:"-"`
ParentID *primitive.ObjectID `json:"parentId,omitempty" bson:"parentid,omitempty"`
CreatedAt time.Time `json:"createdAt" bson:"createdat,omitempty"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedat,omitempty"`
Parent *Category `json:"parent,omitempty,omitempty" bson:"-"`
ParentID *primitive.ObjectID `json:"parentId,omitempty" bson:"parentId,omitempty"`
// #bson:ignore
Children []*Category `json:"children,omitempty,omitempty" bson:"-"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"`
// #bson:ignore
CreatedBy *User `json:"createdBy,omitempty" bson:"-"`
CreatedByID primitive.ObjectID `json:"createdById" bson:"createdbyid,omitempty"`
CreatedByID primitive.ObjectID `json:"createdById" bson:"createdById,omitempty"`
// #bson:ignore
UpdatedBy *User `json:"updatedBy,omitempty" bson:"-"`
UpdatedByID primitive.ObjectID `json:"updatedById" bson:"updatedbyid,omitempty"`
UpdatedByID primitive.ObjectID `json:"updatedById" bson:"updatedById,omitempty"`
// #bson:ignore
Owner *User `json:"owner,omitempty,omitempty" bson:"-"`
OwnerID primitive.ObjectID `json:"ownerId" bson:"ownerid,omitempty"`
OwnerID primitive.ObjectID `json:"ownerId" bson:"ownerId,omitempty"`
}
func (Category) IsBase() {}
@ -53,7 +55,7 @@ func (this Category) GetOwner() *User { return this.Owner }
type CreateCategoryInput struct {
Title []*TranslatedInput `json:"title" bson:"title,omitempty"`
Body []*TranslatedInput `json:"body,omitempty" bson:"body,omitempty"`
ParentID *primitive.ObjectID `json:"parentId,omitempty" bson:"parentid,omitempty"`
ParentID *primitive.ObjectID `json:"parentId,omitempty" bson:"parentId,omitempty"`
}
type CreateTodoInput struct {
@ -75,8 +77,8 @@ type LoginInput struct {
type LoginResponse struct {
User *User `json:"user" bson:"user,omitempty"`
AccessToken string `json:"accessToken" bson:"accesstoken,omitempty"`
RefreshToken string `json:"refreshToken" bson:"refreshtoken,omitempty"`
AccessToken string `json:"accessToken" bson:"accessToken,omitempty"`
RefreshToken string `json:"refreshToken" bson:"refreshToken,omitempty"`
}
type Mutation struct {
@ -92,17 +94,17 @@ type Todo struct {
ID primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
Title *string `json:"title,omitempty" bson:"title,omitempty"`
Completed *bool `json:"completed,omitempty" bson:"completed,omitempty"`
CreatedAt time.Time `json:"createdAt" bson:"createdat,omitempty"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedat,omitempty"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"`
// #bson:ignore
CreatedBy *User `json:"createdBy,omitempty" bson:"-"`
CreatedByID primitive.ObjectID `json:"createdById" bson:"createdbyid,omitempty"`
CreatedByID primitive.ObjectID `json:"createdById" bson:"createdById,omitempty"`
// #bson:ignore
UpdatedBy *User `json:"updatedBy,omitempty" bson:"-"`
UpdatedByID primitive.ObjectID `json:"updatedById" bson:"updatedbyid,omitempty"`
UpdatedByID primitive.ObjectID `json:"updatedById" bson:"updatedById,omitempty"`
// #bson:ignore
Owner *User `json:"owner,omitempty,omitempty" bson:"-"`
OwnerID primitive.ObjectID `json:"ownerId" bson:"ownerid,omitempty"`
OwnerID primitive.ObjectID `json:"ownerId" bson:"ownerId,omitempty"`
}
func (Todo) IsBase() {}
@ -115,13 +117,13 @@ func (this Todo) GetOwner() *User { return this.Owner }
type Translated struct {
Value string `json:"value" bson:"value,omitempty"`
IsPrimary bool `json:"isPrimary" bson:"isprimary,omitempty"`
IsPrimary bool `json:"isPrimary" bson:"isPrimary,omitempty"`
Language string `json:"language" bson:"language,omitempty"`
}
type TranslatedInput struct {
Value string `json:"value" bson:"value,omitempty"`
IsPrimary bool `json:"isPrimary" bson:"isprimary,omitempty"`
IsPrimary bool `json:"isPrimary" bson:"isPrimary,omitempty"`
Language string `json:"language" bson:"language,omitempty"`
}
@ -132,8 +134,8 @@ type User struct {
Type *string `json:"type,omitempty" bson:"type,omitempty"`
Status *string `json:"status,omitempty" bson:"status,omitempty"`
Verified *bool `json:"verified,omitempty" bson:"verified,omitempty"`
Password *string `json:"-" bson:"password,omitempty"`
Token *string `json:"-" bson:"token,omitempty"`
Password *string `json:"-" bson:"Password,omitempty"`
Token *string `json:"-" bson:"Token,omitempty"`
}
type Role string

View File

@ -22,6 +22,11 @@ func (r *categoryResolver) Parent(ctx context.Context, obj *models.Category) (*m
return categoryService.FindByID(ctx, *obj.ParentID)
}
// Children is the resolver for the children field.
func (r *categoryResolver) Children(ctx context.Context, obj *models.Category) ([]*models.Category, error) {
return categoryService.FindChildren(ctx, obj.ID)
}
// CreatedBy is the resolver for the createdBy field.
func (r *categoryResolver) CreatedBy(ctx context.Context, obj *models.Category) (*models.User, error) {
return userService.FindById(ctx, obj.CreatedByID)

View File

@ -33,6 +33,7 @@ func Login(ctx context.Context, loginInput *models.LoginInput, redisClient redis
user, err := app.FindOne[models.User](ctx, "users", filter)
if err != nil {
logFailedLoginAttempt(ctx, loginInput.Identity, redisClient) // optional
return nil, err
}

View File

@ -16,6 +16,10 @@ func Find(ctx context.Context) ([]*models.Category, error) {
return app.Find[models.Category](ctx, coll, bson.D{})
}
func FindChildren(ctx context.Context, id primitive.ObjectID) ([]*models.Category, error) {
return app.Find[models.Category](ctx, coll, bson.M{"parentId": id})
}
func Create(ctx context.Context, input models.CreateCategoryInput) (*models.Category, error) {
return app.InsertOne[models.Category](ctx, coll, input)
}

37
utils/camelize.go Normal file
View File

@ -0,0 +1,37 @@
package utils
import (
"strings"
"unicode"
)
func Camelize(s string) string {
// If input has no delimiters, assume it's already in camelCase or PascalCase
if !strings.ContainsAny(s, "_- ") {
return s[:1] + s[1:] // No change (optionally lowercase first letter: strings.ToLower(s[:1]) + s[1:])
}
// Otherwise, split and camelCase it
parts := strings.FieldsFunc(s, func(r rune) bool {
return r == '_' || r == '-' || unicode.IsSpace(r)
})
if len(parts) == 0 {
return ""
}
var b strings.Builder
b.WriteString(strings.ToLower(parts[0]))
for _, part := range parts[1:] {
if len(part) == 0 {
continue
}
b.WriteString(strings.ToUpper(part[:1]))
if len(part) > 1 {
b.WriteString(part[1:])
}
}
return b.String()
}