Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple schemas #389

Merged
merged 1 commit into from
Oct 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ var genCmd = cli.Command{
}
}

schemaRaw, err := ioutil.ReadFile(config.SchemaFilename)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
os.Exit(1)
for _, filename := range config.SchemaFilename {
var schemaRaw []byte
schemaRaw, err = ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
os.Exit(1)
}
config.SchemaStr[filename] = string(schemaRaw)
}
config.SchemaStr = string(schemaRaw)

if err = config.Check(); err != nil {
fmt.Fprintln(os.Stderr, "invalid config format: "+err.Error())
Expand Down
14 changes: 8 additions & 6 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,16 @@ var initCmd = cli.Command{
}

func GenerateGraphServer(config *codegen.Config, serverFilename string) {
schemaRaw, err := ioutil.ReadFile(config.SchemaFilename)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
os.Exit(1)
for _, filename := range config.SchemaFilename {
schemaRaw, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
os.Exit(1)
}
config.SchemaStr[filename] = string(schemaRaw)
}
config.SchemaStr = string(schemaRaw)

if err = config.Check(); err != nil {
if err := config.Check(); err != nil {
fmt.Fprintln(os.Stderr, "invalid config format: "+err.Error())
os.Exit(1)
}
Expand Down
4 changes: 2 additions & 2 deletions codegen/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type Build struct {
QueryRoot *Object
MutationRoot *Object
SubscriptionRoot *Object
SchemaRaw string
SchemaFilename string
SchemaRaw map[string]string
SchemaFilename SchemaFilenames
Directives []*Directive
}

Expand Down
7 changes: 6 additions & 1 deletion codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@ func (cfg *Config) normalize() error {
}
}

var sources []*ast.Source
for _, filename := range cfg.SchemaFilename {
sources = append(sources, &ast.Source{Name: filename, Input: cfg.SchemaStr[filename]})
}

var err *gqlerror.Error
cfg.schema, err = gqlparser.LoadSchema(&ast.Source{Name: cfg.SchemaFilename, Input: cfg.SchemaStr})
cfg.schema, err = gqlparser.LoadSchema(sources...)
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion codegen/codegen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ func TestGenerateServer(t *testing.T) {
`
serverFilename := "gen/" + name + "/server/server.go"
cfg := Config{
SchemaStr: schema,
SchemaFilename: SchemaFilenames{"schema.graphql"},
SchemaStr: map[string]string{"schema.graphql": schema},
Exec: PackageConfig{Filename: "gen/" + name + "/exec.go"},
Model: PackageConfig{Filename: "gen/" + name + "/model.go"},
Resolver: PackageConfig{Filename: "gen/" + name + "/resolver.go", Type: "Resolver"},
Expand Down
67 changes: 57 additions & 10 deletions codegen/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"}
// DefaultConfig creates a copy of the default config
func DefaultConfig() *Config {
return &Config{
SchemaFilename: "schema.graphql",
SchemaFilename: SchemaFilenames{"schema.graphql"},
SchemaStr: map[string]string{},
Model: PackageConfig{Filename: "models_gen.go"},
Exec: PackageConfig{Filename: "generated.go"},
}
Expand Down Expand Up @@ -53,19 +54,36 @@ func LoadConfig(filename string) (*Config, error) {
return nil, errors.Wrap(err, "unable to parse config")
}

preGlobbing := config.SchemaFilename
config.SchemaFilename = SchemaFilenames{}
for _, f := range preGlobbing {
matches, err := filepath.Glob(f)
if err != nil {
return nil, errors.Wrapf(err, "failed to glob schema filename %s", f)
}

for _, m := range matches {
if config.SchemaFilename.Has(m) {
continue
}
config.SchemaFilename = append(config.SchemaFilename, m)
}
}

config.FilePath = filename
config.SchemaStr = map[string]string{}

return config, nil
}

type Config struct {
SchemaFilename string `yaml:"schema,omitempty"`
SchemaStr string `yaml:"-"`
Exec PackageConfig `yaml:"exec"`
Model PackageConfig `yaml:"model"`
Resolver PackageConfig `yaml:"resolver,omitempty"`
Models TypeMap `yaml:"models,omitempty"`
StructTag string `yaml:"struct_tag,omitempty"`
SchemaFilename SchemaFilenames `yaml:"schema,omitempty"`
SchemaStr map[string]string `yaml:"-"`
Exec PackageConfig `yaml:"exec"`
Model PackageConfig `yaml:"model"`
Resolver PackageConfig `yaml:"resolver,omitempty"`
Models TypeMap `yaml:"models,omitempty"`
StructTag string `yaml:"struct_tag,omitempty"`

FilePath string `yaml:"-"`

Expand All @@ -84,8 +102,37 @@ type TypeMapEntry struct {
}

type TypeMapField struct {
Resolver bool `yaml:"resolver"`
FieldName string `yaml:"fieldName"`
Resolver bool `yaml:"resolver"`
FieldName string `yaml:"fieldName"`
}

type SchemaFilenames []string

func (a *SchemaFilenames) UnmarshalYAML(unmarshal func(interface{}) error) error {
var single string
err := unmarshal(&single)
if err == nil {
*a = []string{single}
return nil
}

var multi []string
err = unmarshal(&multi)
if err != nil {
return err
}

*a = multi
return nil
}

func (a SchemaFilenames) Has(file string) bool {
for _, existing := range a {
if existing == file {
return true
}
}
return false
}

func (c *PackageConfig) normalize() error {
Expand Down
4 changes: 2 additions & 2 deletions codegen/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestLoadDefaultConfig(t *testing.T) {

cfg, err = LoadConfigFromDefaultLocations()
require.NoError(t, err)
require.Equal(t, cfg.SchemaFilename, "inner")
require.Equal(t, SchemaFilenames{"inner"}, cfg.SchemaFilename)
})

t.Run("will find config in parent dirs", func(t *testing.T) {
Expand All @@ -45,7 +45,7 @@ func TestLoadDefaultConfig(t *testing.T) {

cfg, err = LoadConfigFromDefaultLocations()
require.NoError(t, err)
require.Equal(t, cfg.SchemaFilename, "outer")
require.Equal(t, SchemaFilenames{"outer"},cfg.SchemaFilename)
})

t.Run("will return error if config doesn't exist", func(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion codegen/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ func TestTypeInInput(t *testing.T) {

func generate(name string, schema string, typemap ...TypeMap) error {
cfg := Config{
SchemaStr: schema,
SchemaFilename: SchemaFilenames{"schema.graphql"},
SchemaStr: map[string]string{"schema.graphql": schema},
Exec: PackageConfig{Filename: "gen/" + name + "/exec.go"},
Model: PackageConfig{Filename: "gen/" + name + "/model.go"},
}
Expand Down
2 changes: 1 addition & 1 deletion codegen/templates/data.go

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion codegen/templates/generated.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,7 @@ func (ec *executionContext) introspectType(name string) *introspection.Type {
}

var parsedSchema = gqlparser.MustLoadSchema(
&ast.Source{Name: {{.SchemaFilename|quote}}, Input: {{.SchemaRaw|rawQuote}}},
{{- range $filename, $schema := .SchemaRaw }}
&ast.Source{Name: {{$filename|quote}}, Input: {{$schema|rawQuote}}},
{{- end }}
)
Empty file added codegen/testdata/cfg/outer
Empty file.
Empty file.
1 change: 0 additions & 1 deletion codegen/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ type Embed struct {
}

func parseScope(t *testing.T, input interface{}, packageName string) (*types.Scope, error) {
t.Helper()
// test setup to parse the types
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "test.go", input, 0)
Expand Down
10 changes: 10 additions & 0 deletions docs/content/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@ gqlgen can be configured using a `gqlgen.yml` file, by default it will be loaded

Example:
```yml
# You can pass a single schema file
schema: schema.graphql

# Or multiple files
schema:
- schema.graphql
- user.graphql

# Or you can use globs
schema:
- "*.graphql"

# Let gqlgen know where to put the generated server
exec:
filename: graph/generated/generated.go
Expand Down
2 changes: 1 addition & 1 deletion example/config/.gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Refer to https://gqlgen.com/config/
# for detailed .gqlgen.yml documentation.

schema: schema.graphql
schema: "*.graphql"
exec:
filename: generated.go
model:
Expand Down
27 changes: 12 additions & 15 deletions example/config/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 0 additions & 22 deletions example/config/schema.graphql
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
# GraphQL schema example
#
# https://gqlgen.com/getting-started/

type Todo {
id: ID!
databaseId: Int!
text: String!
done: Boolean!
user: User!
}

type User {
id: ID!
name: String!
}

type Query {
todos: [Todo!]!
}

input NewTodo {
text: String!
userId: String!
}

type Mutation {
createTodo(input: NewTodo!): Todo!
}
13 changes: 13 additions & 0 deletions example/config/todo.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type Todo {
id: ID!
databaseId: Int!
text: String!
done: Boolean!
user: User!
}

input NewTodo {
text: String!
userId: String!
}

4 changes: 4 additions & 0 deletions example/config/user.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type User {
id: ID!
name: String!
}
10 changes: 5 additions & 5 deletions integration/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion integration/gqlgen.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
schema: schema.graphql
schema:
- "schema.graphql"
- "user.graphql"

exec:
filename: generated.go
Expand Down
5 changes: 0 additions & 5 deletions integration/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ input DateFilter {
op: DATE_FILTER_OP = EQ
}

type User {
name: String!
likes: [String!]!
}

type Viewer {
user: User
}
Expand Down
4 changes: 4 additions & 0 deletions integration/user.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type User {
name: String!
likes: [String!]!
}