0
votes

How can I export field definitions in GraphQL? For example, let's say I have

schema.graphql:

type Query {
  comment: String!
}

can I instead do something like this?

query.graphql:

const query = comment: String!;

export query;

schema.graphql:

import { query } from './query.graphql';

type Query {
  query
}

EDIT: The real intent behind this question is how do you organize your Querys or Mutations by schema? For example:

type Mutation {
  createComment(data: CreateCommentInput): Comment!,
  createPost(data: CreatePostInput): Post!,
  createUser(data: CreateUserInput): User!,
  deleteComment(id: ID!): Comment!,
  deletePost(id: ID!): Post!,
  deleteUser(id: ID!): User!,
}

Right now my application only has three objects: Comments, Posts, and Users. My preference is to organize my Inputs, Resolvers, etc by schema (e.g. Comments, Posts, and Users), but that means at the end of the day I still have to put everything into a single Mutation type. This seems quite difficult to scale for much larger applications where there could be dozens and dozens of objects and relations, mutations, and more, and it would be nice to separate out individual mutations in their respective Comments folder, Users folder, etc. Thanks!

1

1 Answers

3
votes

GraphQL does not support any kind of import/export syntax.

Certain libraries like graphql-tag and babel-plugin-import-graphql support importing fragments or type definitions through comments, but these libraries do not support importing individual field definitions.

At best, you could utilize template strings, but you'd have to utilize JavaScript/TypeScript files instead (assuming you're working with a Node.js server, but that's not totally clear from your question).

fields.js

export const fields = `
  comment: String!
`

query.js

import { fields } from './fields' 

export const typeDefs = `
  type Query {
    ${fields}
  }
`

At the end of the day, though, it's unlikely you have enough duplication between your type definitions to warrant doing something like this. Unless you have dozens of common fields across dozens of types, I would just deal with the duplication.

If you're just looking to modularize your schema across multiple files, you can use the extend to create multiple type definitions that will be merged into a single one. For example:

type Query {
  someField: String!
}

extend type Query {
  someOtherField: String!
}

extend type Query {
  yetAnotherField: String!
}

Not that you must still define the type you're extending -- you cannot have extensions that reference a non-existent type. When using extensions, however, your "base" type doesn't necessarily have to have fields (as long as you have at least one extension). So you can do something like this as well:

type Query # Note the lack of curly brackets

extend type Query {
  someOtherField: String!
}

There are also libraries out there, like this one, that let you merge type definitions without using the extend keyword. There are some known issues with this sort of programmatic merging, but YMMV.

Lastly, although I'm personally not a fan of doing things this way, you may find this pattern helpful in organizing your schema.