-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3fede10
commit 0413eec
Showing
10 changed files
with
278 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,75 @@ | ||
package gqlgenerate | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"os" | ||
|
||
"github.com/99designs/gqlgen/api" | ||
"github.com/99designs/gqlgen/codegen/config" | ||
"github.com/99designs/gqlgen/plugin/modelgen" | ||
"github.com/vektah/gqlparser/v2/ast" | ||
) | ||
|
||
// Exit codes | ||
const ( | ||
exitCodeConfigLoadError = 2 | ||
exitCodeGenerateError = 3 | ||
) | ||
|
||
func main() { | ||
// Initialize logger | ||
logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) | ||
|
||
// Load the GraphQL configuration | ||
cfg, err := loadGraphQLConfig() | ||
if err != nil { | ||
logger.Fatalf("Error loading GraphQL config: %v", err) | ||
} | ||
|
||
// Generate the GraphQL server code | ||
err = generateGraphQLCode(cfg, logger) | ||
if err != nil { | ||
logger.Fatalf("Error generating GraphQL code: %v", err) | ||
} | ||
} | ||
|
||
// loadGraphQLConfig loads the GraphQL configuration from default locations | ||
func loadGraphQLConfig() (*config.Config, error) { | ||
cfg, err := config.LoadConfigFromDefaultLocations() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to load config: %w", err) | ||
} | ||
return cfg, nil | ||
} | ||
|
||
// generateGraphQLCode generates the GraphQL server code using the provided config | ||
func generateGraphQLCode(cfg *config.Config, logger *log.Logger) error { | ||
// Attaching the mutation function onto modelgen plugin | ||
p := modelgen.Plugin{ | ||
FieldHook: ValidationFieldHook, | ||
} | ||
|
||
// Generate the code using the API | ||
err := api.Generate(cfg, api.ReplacePlugin(&p)) | ||
if err != nil { | ||
return fmt.Errorf("code generation failed: %w", err) | ||
} | ||
logger.Println("GraphQL code generation successful") | ||
return nil | ||
} | ||
|
||
// ValidationFieldHook is a custom hook for adding validation tags to fields based on directives | ||
func ValidationFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *modelgen.Field) (*modelgen.Field, error) { | ||
// Look for the "validation" directive on the field | ||
c := fd.Directives.ForName("validation") | ||
if c != nil { | ||
// Add validation tag based on the "format" argument in the directive | ||
formatConstraint := c.Arguments.ForName("format") | ||
if formatConstraint != nil { | ||
// Use a format that avoids double quoting | ||
f.Tag += fmt.Sprintf(` validate:"%s"`, formatConstraint.Value.Raw) | ||
} | ||
} | ||
return f, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"testing" | ||
|
||
"github.com/99designs/gqlgen/plugin/modelgen" | ||
"github.com/vektah/gqlparser/v2/ast" | ||
) | ||
|
||
func TestLoadGraphQLConfig(t *testing.T) { | ||
_, err := loadGraphQLConfig() | ||
if err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
} | ||
|
||
func TestGenerateGraphQLCode(t *testing.T) { | ||
logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) | ||
cfg, err := loadGraphQLConfig() | ||
if err != nil { | ||
t.Fatalf("Failed to load config: %v", err) | ||
} | ||
|
||
err = generateGraphQLCode(cfg, logger) | ||
if err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
} | ||
|
||
func TestValidationFieldHook(t *testing.T) { | ||
// Mock field definitions and directive | ||
fd := &ast.FieldDefinition{ | ||
Directives: ast.DirectiveList{ | ||
{ | ||
Name: "validation", | ||
Arguments: ast.ArgumentList{ | ||
{ | ||
Name: "format", | ||
Value: &ast.Value{ | ||
Raw: "email", | ||
Kind: ast.StringValue, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
f := &modelgen.Field{} | ||
|
||
_, err := ValidationFieldHook(nil, fd, f) | ||
if err != nil { | ||
t.Fatalf("Expected no error, got %v", err) | ||
} | ||
|
||
expectedTag := ` validate:"email"` | ||
if f.Tag != expectedTag { | ||
t.Fatalf("Expected tag %v, got %v", expectedTag, f.Tag) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,3 +85,6 @@ models: | |
Time: | ||
model: | ||
- github.com/99designs/gqlgen/graphql.Time | ||
directives: | ||
validation: | ||
skip_runtime: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,51 @@ | ||
package graph | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"regexp" | ||
|
||
"github.com/99designs/gqlgen/graphql" | ||
) | ||
|
||
//gqlgen | ||
|
||
// | ||
// #directive @constraint( | ||
//# minLength: Int, | ||
//# maxLength: Int, | ||
//# min: Int, | ||
//# max: Int, | ||
//# pattern: String) on INPUT_FIELD_DEFINITION | ||
|
||
func Constraint(ctx context.Context, obj interface{}, next graphql.Resolver, minLength *int, maxLength *int, min *int, max *int, pattern *string) (interface{}, error) { | ||
val, err := next(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
switch v := val.(type) { | ||
case string: | ||
if minLength != nil && len(v) < *minLength { | ||
return nil, errors.New("value is too short") | ||
} | ||
if maxLength != nil && len(v) > *maxLength { | ||
return nil, errors.New("value is too long") | ||
} | ||
if pattern != nil { | ||
matched, _ := regexp.MatchString(*pattern, v) | ||
if !matched { | ||
return nil, errors.New("value does not match pattern") | ||
} | ||
} | ||
case int: | ||
if min != nil && v < *min { | ||
return nil, errors.New("value is too small") | ||
} | ||
if max != nil && v > *max { | ||
return nil, errors.New("value is too large") | ||
} | ||
} | ||
|
||
return val, nil | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.