Skip to content

Commit

Permalink
chore: fix linter issues (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
tessig committed Nov 1, 2023
1 parent a2d450f commit d12d354
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ linters:
issues:
new: false
fix: false
new-from-rev: 2b6063ac3c145007726044a5555b6d2a40d3b089
exclude-rules:
- path: _test\.go
linters:
Expand Down Expand Up @@ -113,5 +112,6 @@ linters-settings:
ignore-names:
- err
- id
- to
ignore-decls:
- i int
116 changes: 73 additions & 43 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (
const (
basePath = "graphql"
schemaBasePath = "graphql/schema"

filePermission755 = 0755
filePermission644 = 0644
)

var skipGoModTidy = true
Expand Down Expand Up @@ -56,28 +59,18 @@ func Generate(services []Service, basePath string, schemaBasePath string) error
schemaPath := path.Join(schemaBasePath, "schema.graphql")

cfg := config.DefaultConfig()

err := config.CompleteConfig(cfg)
if err != nil {
return err
return fmt.Errorf("failed to complete the config: %w", err)
}

cfg.SchemaFilename = []string{schemaPath}
cfg.Models = make(map[string]config.TypeMapEntry)

if err := os.MkdirAll(schemaBasePath, 0755); err != nil && !os.IsExist(err) {
return fmt.Errorf("mkdir %q failed: %w", schemaBasePath, err)
}

if err := os.WriteFile(schemaPath, schema, 0644); err != nil {
return fmt.Errorf("writefile %q failed: %w", schemaPath, err)
}

if err := os.WriteFile(path.Join(basePath, "module.go"), module, 0644); err != nil {
return fmt.Errorf("writefile %q/module.go failed: %w", basePath, err)
}

if err := os.WriteFile(path.Join(basePath, "emptymodule.go"), emptyModule, 0644); err != nil {
return fmt.Errorf("writefile %q/emptymodule.go failed: %w", basePath, err)
err = createFiles(schemaBasePath, schemaPath, basePath)
if err != nil {
return err
}

types := new(Types)
Expand All @@ -91,40 +84,17 @@ func Generate(services []Service, basePath string, schemaBasePath string) error
fpath := path.Join(schemaBasePath, fname)

log.Printf("Writing %s", fname)
if err := os.WriteFile(fpath, service.Schema(), 0644); err != nil {

if err := os.WriteFile(fpath, service.Schema(), filePermission644); err != nil {
return fmt.Errorf("writefile %q failed: %w", fpath, err)
}

cfg.SchemaFilename = append(cfg.SchemaFilename, fpath)

service.Types(types)
}

// merge models into config models
for graphqlObject, goType := range types.names {
cfg.Models[graphqlObject] = config.TypeMapEntry{Model: []string{goType}}
}

for graphqlObject, fields := range types.fields {
for graphqlField, goType := range fields {
model := cfg.Models[graphqlObject]
if cfg.Models[graphqlObject].Fields == nil {
model.Fields = make(map[string]config.TypeMapField)
}
model.Fields[graphqlField] = config.TypeMapField{FieldName: goType}
cfg.Models[graphqlObject] = model
}
}

for graphqlObject, resolver := range types.resolver {
for graphqlField := range resolver {
model := cfg.Models[graphqlObject]
if cfg.Models[graphqlObject].Fields == nil {
model.Fields = make(map[string]config.TypeMapField)
}
model.Fields[graphqlField] = config.TypeMapField{Resolver: true}
cfg.Models[graphqlObject] = model
}
}
mergeModels(types, cfg)

float := cfg.Models["Float"]
float.Model = append(float.Model, "flamingo.me/graphql.Float", "github.com/99designs/gqlgen/graphql.Float")
Expand All @@ -150,9 +120,61 @@ func Generate(services []Service, basePath string, schemaBasePath string) error
if err := api.Generate(cfg, api.AddPlugin(&plugin{types: types})); err != nil {
return fmt.Errorf("gqlgen/api.Generate failed: %w", err)
}

return nil
}

func createFiles(schemaBasePath string, schemaPath string, basePath string) error {
if err := os.MkdirAll(schemaBasePath, filePermission755); err != nil && !os.IsExist(err) {
return fmt.Errorf("mkdir %q failed: %w", schemaBasePath, err)
}

if err := os.WriteFile(schemaPath, schema, filePermission644); err != nil {
return fmt.Errorf("writefile %q failed: %w", schemaPath, err)
}

if err := os.WriteFile(path.Join(basePath, "module.go"), module, filePermission644); err != nil {
return fmt.Errorf("writefile %q/module.go failed: %w", basePath, err)
}

if err := os.WriteFile(path.Join(basePath, "emptymodule.go"), emptyModule, filePermission644); err != nil {
return fmt.Errorf("writefile %q/emptymodule.go failed: %w", basePath, err)
}

return nil
}

// merge models into config models
func mergeModels(types *Types, cfg *config.Config) {
for graphqlObject, goType := range types.names {
cfg.Models[graphqlObject] = config.TypeMapEntry{Model: []string{goType}}
}

for graphqlObject, fields := range types.fields {
for graphqlField, goType := range fields {
model := cfg.Models[graphqlObject]
if cfg.Models[graphqlObject].Fields == nil {
model.Fields = make(map[string]config.TypeMapField)
}

model.Fields[graphqlField] = config.TypeMapField{FieldName: goType}
cfg.Models[graphqlObject] = model
}
}

for graphqlObject, resolver := range types.resolver {
for graphqlField := range resolver {
model := cfg.Models[graphqlObject]
if cfg.Models[graphqlObject].Fields == nil {
model.Fields = make(map[string]config.TypeMapField)
}

model.Fields[graphqlField] = config.TypeMapField{Resolver: true}
cfg.Models[graphqlObject] = model
}
}
}

var _ plugin2.CodeGenerator = &plugin{}
var _ plugin2.ConfigMutator = &plugin{}
var _ plugin2.Plugin = &plugin{}
Expand Down Expand Up @@ -184,7 +206,8 @@ func (m *plugin) GenerateCode(data *codegen.Data) error {
panic("code generation failed")
}
}()
return gqltemplates.Render(gqltemplates.Options{

err := gqltemplates.Render(gqltemplates.Options{
PackageName: "graphql",
Filename: "graphql/resolver.go",
Data: &resolverBuild{
Expand All @@ -196,6 +219,7 @@ func (m *plugin) GenerateCode(data *codegen.Data) error {
Funcs: template.FuncMap{
"gpkg": func(from, to string, field codegen.Field) string {
if m.types.resolver[from][to][0] == "" {
//nolint: forbidigo // special case of error output
fmt.Printf(
"\nmissing resolver for %q.%q:\n\tfunc (r *%sResolver) %s%s\n\n\ttypes.Resolve(\"%s\", \"%s\", %sResolver{}, \"%s\")\n\n",
from, to,
Expand Down Expand Up @@ -346,6 +370,12 @@ func direct(root *{{$root.TypeName}}) map[string]interface{} {
}
`,
})

if err != nil {
return fmt.Errorf("failed to render generation template: %w", err)
}

return nil
}

type resolverBuild struct {
Expand Down
1 change: 1 addition & 0 deletions corshandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func (h *corsHandler) validateOrigin(origin string) bool {
return true
}
}

return false
}

Expand Down
12 changes: 10 additions & 2 deletions example/todo/infrastructure/todo.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ var todos = []*domain.Todo{
{ID: "task-2", Task: "task c"},
}

var (
ErrNoTodoGiven = errors.New("no todo given")
ErrTodoNotFound = errors.New("todo not found")
)

// Todos returns a list of mocked todos
func (ts *TodoService) Todos(_ context.Context, _ string) ([]*domain.Todo, error) {
return todos, nil
Expand All @@ -25,13 +30,15 @@ func (ts *TodoService) Todos(_ context.Context, _ string) ([]*domain.Todo, error
// AddTodo mutation adds an entry to the list
func (ts *TodoService) AddTodo(_ context.Context, _ string, task string) (*domain.Todo, error) {
if task == "" {
return nil, errors.New("no todo given")
return nil, ErrNoTodoGiven
}

todo := &domain.Todo{
ID: "task-" + strconv.Itoa(len(todos)),
Task: task,
}
todos = append(todos, todo)

return todo, nil
}

Expand All @@ -43,5 +50,6 @@ func (ts *TodoService) TodoDone(_ context.Context, todoID string, done bool) (*d
return todos[i], nil
}
}
return nil, errors.New("todo not found")

return nil, ErrTodoNotFound
}
22 changes: 19 additions & 3 deletions example/todo/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package todo

import (
"context"
"fmt"

"flamingo.me/graphql/example/todo/domain"
"flamingo.me/graphql/example/todo/infrastructure"
Expand All @@ -21,7 +22,12 @@ func (r *UserResolver) Inject(todosBackend *infrastructure.TodoService) *UserRes

// Todos getter
func (r *UserResolver) Todos(ctx context.Context, obj *userDomain.User) ([]*domain.Todo, error) {
return r.todosBackend.Todos(ctx, obj.Name)
todos, err := r.todosBackend.Todos(ctx, obj.Name)
if err != nil {
return nil, fmt.Errorf("can not load todos: %w", err)
}

return todos, nil
}

// MutationResolver maps mutations
Expand All @@ -37,10 +43,20 @@ func (r *MutationResolver) Inject(resolver *UserResolver) *MutationResolver {

// TodoAdd mutation
func (r *MutationResolver) TodoAdd(ctx context.Context, user string, task string) (*domain.Todo, error) {
return r.resolver.todosBackend.AddTodo(ctx, user, task)
todo, err := r.resolver.todosBackend.AddTodo(ctx, user, task)
if err != nil {
return nil, fmt.Errorf("can not add todo: %w", err)
}

return todo, nil
}

// TodoDone mutation
func (r *MutationResolver) TodoDone(ctx context.Context, todo string, done bool) (*domain.Todo, error) {
return r.resolver.todosBackend.TodoDone(ctx, todo, done)
todoDone, err := r.resolver.todosBackend.TodoDone(ctx, todo, done)
if err != nil {
return nil, fmt.Errorf("can not update todo: %w", err)
}

return todoDone, nil
}
8 changes: 7 additions & 1 deletion example/user/domain/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,22 @@ type UserService interface {

// Get returns an attribute by its key
func (a Attributes) Get(key string) string {
return a[key].(string)
if s, ok := a[key].(string); ok {
return s
}

return ""
}

// Keys lists all attribute keys
func (a Attributes) Keys() []string {
keys := make([]string, len(a))
i := 0

for k := range a {
keys[i] = k
i++
}

return keys
}
8 changes: 7 additions & 1 deletion example/user/interfaces/graphql/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package graphql
import (
"context"
"errors"
"fmt"
"strings"

"flamingo.me/graphql/example/user/domain"
Expand All @@ -24,7 +25,12 @@ func (r *UserQueryResolver) Inject(userService domain.UserService) *UserQueryRes

// User getter
func (r *UserQueryResolver) User(ctx context.Context, id string) (*domain.User, error) {
return r.userService.UserByID(ctx, id)
user, err := r.userService.UserByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("can not load user: %w", err)
}

return user, nil
}

// UserAttributeFilter directive
Expand Down
11 changes: 9 additions & 2 deletions graphqlhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package graphql

import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
Expand All @@ -21,19 +22,25 @@ func wrapGqlHandler(handler http.Handler) web.Action {
return func(ctx context.Context, req *web.Request) web.Result {
rw := httptest.NewRecorder()
handler.ServeHTTP(rw, req.Request().WithContext(ctx))

return &gqlHandler{
request: req,
recorder: rw,
}
}
}

func (h *gqlHandler) Apply(ctx context.Context, rw http.ResponseWriter) error {
func (h *gqlHandler) Apply(_ context.Context, rw http.ResponseWriter) error {
for k, vs := range h.recorder.Header() {
for _, v := range vs {
rw.Header().Add(k, v)
}
}

_, err := io.Copy(rw, h.recorder.Body)
return err
if err != nil {
return fmt.Errorf("failed to write body: %w", err)
}

return nil
}
4 changes: 4 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (tc *Types) Resolve(graphqlType, graphqlField string, typ interface{}, meth
if tc.resolver == nil {
tc.resolver = make(map[string]map[string][3]string)
}

if tc.resolver[graphqlType] == nil {
tc.resolver[graphqlType] = make(map[string][3]string)
}
Expand All @@ -40,6 +41,7 @@ func (tc *Types) Resolve(graphqlType, graphqlField string, typ interface{}, meth
for t.Kind() == reflect.Ptr {
t = t.Elem()
}

tc.resolver[graphqlType][graphqlField] = [3]string{t.PkgPath(), t.Name(), method}
}

Expand All @@ -48,9 +50,11 @@ func (tc *Types) GoField(graphqlType, graphqlField, goField string) {
if tc.fields == nil {
tc.fields = make(map[string]map[string]string)
}

if tc.fields[graphqlType] == nil {
tc.fields[graphqlType] = make(map[string]string)
}

tc.fields[graphqlType][graphqlField] = goField
}

Expand Down

0 comments on commit d12d354

Please sign in to comment.