anli
anli

Reputation: 735

How can I combine a GraphQLObjectType with a schema created by graphql-tag with gql-tag?

I use graphql-tag together with apollo-server-express to connect to build a graphQL endpoint for an api. At the moment I create the schema definition like this:

properties.js

let model = {}
const typeDefs = gql`
    extend type Query {
        property(id: Int!): [Property]
    }
    
    type Property {
        title: String
        street: String
        postalcode: String
        city: String
        country: String
    }
`
const resolvers = {
    Query: {
        property: getTheEntriesFromDB,
    },
}

model.typeDefs = typeDefs;
model.resolvers = resolvers;

module.exports = model;

and server.js

const server = new ApolloServer({
    modules: [
        require('./modules/properties'),
    ],
}):

However I want to create the type 'Property' based on a database schema automatically. I found out that I can create a GraphQLObjectType like this:

const propertyType = new graphql.GraphQLObjectType({
    name: 'Property',
    fields: {
        title: { type: graphql.GraphQLString },
        street: { type: graphql.GraphQLString },
        postalcode: { type: graphql.GraphQLString },
        city: { type: graphql.GraphQLString },
        country: { type: graphql.GraphQLString },
    }
});

but I don't know how to combine this with

let model = {}
const typeDefs = gql`
    extend type Query {
        property(id: Int!): [Property]
    }
`
const resolvers = {
    Query: {
        property: getTheEntriesFromDB,
    },
}

model.typeDefs = typeDefs;
model.resolvers = resolvers;

module.exports = model;

to create the final schema. Can someone point me in the right direction? Any help is highly appreciated. Thanks a lot in advance!

Upvotes: 0

Views: 790

Answers (1)

anli
anli

Reputation: 735

OK, after hours of trial and error and searching I found this solution which works for me:

properties.js

const { buildASTSchema, GraphQLObjectType, GraphQLSchema, GraphQLString, parse, printSchema } = require('graphql')

let model = {}

const propertyType = new GraphQLObjectType({
    name: 'Property',
    fields: {
        title: { type: GraphQLString },
        street: { type: GraphQLString },
        postalcode: { type: GraphQLString },
        city: { type: GraphQLString },
        country: { type: GraphQLString },
    }
});

let typeDefs = gql`
    extend type Query {
        property(id: Int!): [Property]
    }
    
    type Property {
        id: Int
    }
`

typeDefs.definitions[0].kind = 'ObjectTypeDefinition' //replace ObjectTypeExtension with ObjectTypeDefinition to make AST 'valid' but keep extend in gql-tag to satisfy code inspection in ide
typeDefs = parse(printSchema(buildASTSchema(typeDefs)).replace('type Query {', 'extend type Query {') + printSchema(new GraphQLSchema({ types: [ propertyType ]})).replace('type Property {', 'extend type Property {'))

const resolvers = {
    Query: {
        property: getTheEntriesFromDB,
    },
}

model.typeDefs = typeDefs;
model.resolvers = resolvers;

module.exports = model;

The "extend" keywords are needed because Property needs to be declared inside the gql tag and Query is declared more than once throughout the project.

Upvotes: 1

Related Questions