Skip to content

Commit

Permalink
Merge pull request 99designs#389 from 99designs/multiple-schemas
Browse files Browse the repository at this point in the history
Support multiple schemas
  • Loading branch information
vektah authored Oct 21, 2018
2 parents 43af2cd + c1ba3a6 commit edc8c7c
Show file tree
Hide file tree
Showing 23 changed files with 143 additions and 80 deletions.
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!]!
}

0 comments on commit edc8c7c

Please sign in to comment.