Graphql-yoga: Modularized Resolvers and TypeDefs - Error: typeDefs.reduce is not a function

Created on 16 Mar 2018  Â·  11Comments  Â·  Source: dotansimha/graphql-yoga

I am trying to place resolvers and typeDefs in separate files using merge-graphql-schemas. They are successfully merged however, I am getting this error when they reach new GraphQLServer({...}). Any help would be appreciated.

Error

TypeError: typeDefs.reduce is not a function
    at mergeTypeDefs (/[path...]/typeorm-demo/node_modules/graphql-yoga/src/index.ts:313:19)

Files

I have 2 .ts resolvers and 2 .graphql typeDefs formatted like:

_#/resolvers/simple.resolver.ts_

export default {
  Query: {
    beerMe: (_, { name }) => `Beer ${name || "Served"}`
  }
};

_#/typeDefs/simple.typeDef.graphql_

type Query {
  beerMe(name: String): String!
}

_#/typeDefs/index.ts

import * as path from "path";
import { fileLoader, mergeTypes } from "merge-graphql-schemas";

const typesArray = fileLoader(path.join(__dirname, "./"));
const typesMerged = mergeTypes(typesArray, { all: false });
console.log("typesMerged", typesMerged);
export default typesMerged;

_#/resolvers/index.ts_

import { mergeResolvers } from "merge-graphql-schemas";
import userResolver from "./user.resolvers";
import simpleResolver from "./simple.resolvers";

const resolversArray = [userResolver, simpleResolver];
const resolvers = mergeResolvers(resolversArray);
console.log("merged resolvers", resolvers);
export default resolvers;

_#scr/index.ts_

import "reflect-metadata";
import { createConnection } from "typeorm";
import { IResolvers } from "graphql-yoga/dist/src/types";
import { GraphQLServer } from "graphql-yoga";

const resolvers = require("./resolvers");
const typeDefs = require("./typeDefs");
const server = new GraphQLServer({ typeDefs, resolvers });
createConnection().then(() => {
  server.start(() => console.log("Server is running on localhost:4000"));
});

Directory structure

|____entity
| |____Profile.ts
| |____User.mysql-version.ts.bak
| |____User.ts
|____index.ts
|____resolvers
| |____index.ts
| |____simple.resolvers.ts
| |____user.resolvers.ts
|____typeDefs
| |____index.ts
| |____simple.typedefs.graphql
| |____user.typedefs.graphql
statupr-welcome

All 11 comments

This seems like a bug. Thanks for reporting @jboothe. Can you please create a repo which we can use to reproduce the problem?

Sure can. https://github.com/jboothe/typeorm-graphql-demo.

Thanks for taking a look.

You should import it differently:
import { default as typeDefs } from './typeDefs'
because when you import it with require its in this shape:

{ default: 'schema {\n  query: Query\n  mutation: Mutation\n}\n\ntype Query {\n  beerMe(name: String): String!\n  user(id: Int!): User!\n  users: [User!]!\n}\n\ntype Mutation {\n  createUser(firstName: String!, lastName: String!, age: Int!, email: String!, profile: ProfileInput): User!\n  updateUser(id: Int!, firstName: String, lastName: String, age: Int, email: String): Boolean\n  deleteUser(id: Int!): Boolean\n  deleteUserConditionally(id: Int!): Boolean\n}\n\ntype User {\n  id: Int!\n  firstName: String!\n  lastName: String!\n  email: String!\n  age: Int!\n  profile: Profile\n}\n\ntype Profile {\n  id: Int!\n  gender: String!\n  photo: String\n}\n\ninput ProfileInput {\n  gender: String!\n  photo: String\n}\n' }

so you need to add .default or use import how i wrote on top :)

@marktani Wanted to add more insight. Your provided Object to mergeTypeDefs what is not supported. Currently is supported string, array, documentNode. So maybe there should be some better error handling to show proper error. So there is missing check for array and if it's not an array just throw error :) I can add it to my PR #220 and add it to documentation with this fix extra.

Thanks @Huvik 🎉 . Using that import syntax on both resolvers and typeDefs solved the issue.

import { default as typeDefs } from './typeDefs'
import { default as resolvers } from './resolvers'

Great, thanks for the confirmation @jboothe! I am hoping this helps you progress with #136. I'd be curious to hear more about this.

@Huvik, it would be great if you can include the improvements you mentioned in a new PR.

Thanks all :raised_hands:

I'm on it. If it helps others remove that barrier, I'm glad to help.

@jboothe Can you please tell how you imported types from 'generated/prisma.graphql' into the individual modules .graphql files in the typeDefs folder? When I try following this, I get Type "<typeName>" not found in the document.

@Alosies can you create a new issue with a reproduction example? :slightly_smiling_face:

I'm currently trying this with prism using merge resolvers, but my user listings aren't showing.

src/schema.graphql

# import Listing from './generated/prisma.graphql'
# import User from './generated/prisma.graphql'

type Query {
  listings(searchString: String): [Listing!]!
  listing(id: ID!): Listing
  users(searchString: String): [User!]!
  user(id: ID!): User
}

type Mutation {
  createDraft(authorId: ID!, title: String!, content: String!): Listing
  publish(id: ID!): Listing
  deleteListing(id: ID!): Listing
  createUser(username: String!, email: String!, name: String!, firstName: String!, lastName: String!): User!
}

src/resolvers/index.js

import * as path from "path";
import { mergeResolvers, fileLoader } from "merge-graphql-schemas";

const resolversArray = fileLoader(path.join(__dirname, "./**/*.resolvers.*"));

const resolvers = mergeResolvers(resolversArray);

export default resolvers;

src/resolvers/listing.resolvers.js

export default {

  Query: {
    listings: (_, args, context, info) => {
      return context.prisma.query.listings(
        {
          where: {
            OR: [
              { title_contains: args.searchString },
              { content_contains: args.searchString },
            ],
          },
        },
        info,
      )
    }
  },
  Mutation: {
    createDraft: (_, args, context, info) => {
      return context.prisma.mutation.createListing(
        {
          data: {
            title: args.title,
            content: args.title,
            author: {
              connect: {
                id: args.authorId,
              },
            },
          },
        },
        info,
      )
    },
    publish: (_, args, context, info) => {
      return context.prisma.mutation.updateListing(
        {
          where: {
            id: args.id,
          },
          data: {
            published: true,
          },
        },
        info,
      )
    },
    deleteListing: (_, args, context, info) => {
      return context.prisma.mutation.deleteListing(
        {
          where: {
            id: args.id,
          },
        },
        info,
      )
    },

  },
}

src/resolvers/user.resolvers.js

export default {

    Query: {

      users: (_, args, context, info) => {
        return context.prisma.query.users(
          info,
        )
      },
      user: (_, args, context, info) => {
        return context.prisma.query.user(
          {
            where: {
              id: args.id,
            },
          },
          info,
        )
      },

    },

    Mutation: {
    createUser: (_, args, context, info) => {
      return context.prisma.mutation.createUser(
        {
          data: {
            name: args.name,
            username: args.username,
            email: args.email,
            firstName: args.firstName,
            lastName: args.lastName,
          },
        },
        info,
      )
    },
  }


}

src/index.js

import { GraphQLServer } from 'graphql-yoga';
import { Prisma } from 'prisma-binding';
import { default as resolvers } from './resolvers';

const options = { port: 1337 };

const server = new GraphQLServer({
  typeDefs: 'src/schema.graphql',
  resolvers,
  context: req => ({
    ...req,
    prisma: new Prisma({
      typeDefs: 'src/generated/prisma.graphql',
      endpoint: 'http://localhost:4466',
    }),
  }),
});
server.start(options, () => console.log(`Server is running âš¡ on localhost:${options.port}`)).catch(err => console.error('connection Error', err));

it works, but my users query returns null for listings

{
  "data": {
    "users": [
      {
        "id": "cjizxnenk000e0719e1bx8jvb",
        "username": "jimmyjamieson",
        "name": "Ian Jamieson",
        "firstName": "Ian",
        "lastName": "Jamieson",
        "email": "[email protected]",
        "rating": 0,
        "listings": null
      }
    ]
  }
}

If i copy the resolvers into resolvers/index.js I get the listings showing fine, so I think it has something do do with merge resolvers.

listings are showing the user fine

{
  "data": {
    "listings": [
      {
        "id": "cjizxneoa000f0719ztvy1nla",
        "title": "Test title",
        "content": "lorem ipsum",
        "published": true,
        "author": {
          "id": "cjizxnenk000e0719e1bx8jvb",
          "username": "ianjamieson",
          "name": "Ian Jamieson"
        }
      }
    ]
  }
}

Also, a console.log(resolvers) inside src/resolvers/index.js produces

{ Query:
   { listings: [Function: listings],
     users: [Function: users],
     user: [Function: user] },
  Mutation:
   { createDraft: [Function: createDraft],
     publish: [Function: publish],
     deleteListing: [Function: deleteListing],
     createUser: [Function: createUser] } }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

lautiamkok picture lautiamkok  Â·  4Comments

cj picture cj  Â·  3Comments

anthonymetzler picture anthonymetzler  Â·  4Comments

checkmatez picture checkmatez  Â·  5Comments

ramonmulia picture ramonmulia  Â·  3Comments