userSchema: (author schema like the same)
export const schema = [`
type Email {
address: String
verified: Boolean
}type User {
emails: [Email]
username: String
randomString: String
}
`];
rootSchema:
import { schema as userSchema, resolvers as userResolver } from './user/schema';
const rootSchema = [`
type RootQuery {
author(name: String): Author
user: User
}schema {
query: RootQuery
}
`]export const schema = [...rootSchema, ...userSchema, ...authorSchema];
When I trying to contact schemas into 1 typedefinition in GitHunt way(seems its the only one example had separate schemas), I got this:
[ '\n type RootQuery {\n author(name: String): Author\n user: User\n }\n \n \n schema {\n query: RootQuery\n }\n',
I20160704-11:08:53.149(8)? '\n type Email {\n address: String\n verified: Boolean\n }\n \n type User {\n emails: [Email]\n username: String\n randomString: String\n }\n',
I20160704-11:08:53.149(8)? '\n# This uses the exact field names returned by the GitHub API for simplicity\ntype Author {\n name: String\n books: [Book]\n }\n \n type Book {\n name: String\n author: [Author]\n \n' ] { RootQuery: { user: [Function: user], author: [Function: author] }
Also I found the generateSchema in docs is deprecated. And I have no idea how to use the GraphQLSchema instance generated.
Yes, this is not very well documented at the moment. A type definition can contain other imported type definitions. If they are circular, you can use a function that returns an array as type definition. You should use the makeExecutableSchema function from graphql-tools (not apollo-server) here: https://github.com/apollostack/graphql-tools/blob/88eadb99a11733fb11726df539d6fe1bb3be9a6f/src/schemaGenerator.js#L67
We're planning on making a big push for documentation and content starting next week, so this should be more well-documented soon!
Thanks for answer.
When I trying to use makeExecutableSchema, I still got error when using concated typeDefs:
Am i miss something when doing this?
export const schema = [...rootSchema, ...userSchema, ...authorSchema];
/Users/walter/.meteor/packages/meteor-tool/.1.3.4_1.mi2rro++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:280
W20160704-14:55:00.879(8)? (STDERR) throw(ex);
W20160704-14:55:00.879(8)? (STDERR) ^
W20160704-14:55:00.879(8)? (STDERR) Syntax Error GraphQL (27:21) Expected Name, found EOF
W20160704-14:55:00.880(8)? (STDERR)
W20160704-14:55:00.880(8)? (STDERR) 26: name: String
W20160704-14:55:00.880(8)? (STDERR) 27: author: [Author]
That should work just fine. Are you sure you don't have a syntax error in your file, like a missing } after [Author]?
Yes I fixed it by remove a comment line. Close.
thank you
@helfer could you show a sample, how to use the makeExecutableSchema function?
Yes, I'll write some documentation today or tomorrow, including an example.
@helfer are you ready? Where can I find the docs & example?
up
+1 for docs on merging schemas and resolvers
Sorry for the delay, we're going to do a major rewrite of the documentation soon, so this might actually take even longer. In the meantime, here's the function signature:
function makeExecutableSchema({
typeDefs, // shorthand type definitions
resolvers, // resolve function definitions
connectors,
logger, // logging function to be called for every resolver
allowUndefinedInResolve = false,
resolverValidationOptions = {},
})
The resolver validation options (and defaults) are as follows.
{
requireResolversForArgs = true,
requireResolversForNonScalar = true,
}
@helfer Thanks, but unfortunately it's not solve my problem. My app is modularity, and in every module have queries in the Query. So I need to merge this queries to one before I gave it to the makeExecutableSchema.
For example:
post.module.js
const schema = `
type Query {
posts(limit: Int, offset: Int, sort: String): [Post]
post(id: Int, code: String): Post
}
type Post {
id: Int!
code: String!
title: String
content: String
author: User!
}
type Mutation {
upVote(postID: Int!): Post
downVote(postID: Int!): Post
}
user.module.js
const schema = `
type Query {
users(limit: Int, offset: Int, sort: String): [User]
user(id: Int, code: String): User
}
type User {
id: Int!
code: String!
fullName: String
email: String
username: String
provider: String
roles: [String]
verified: Boolean
gravatar: String
lastLogin: Timestamp
posts(limit: Int, offset: Int, sort: String): [Post]
}
type Mutation {
createUser(userID Int!): User
deleteUser(userID: Int!)
}
`
So I need to merge the Query definitions too. In schemaGenerator the concatenateTypeDefs functions concatenate the typeDefs only.
Are there any solution for this problem in the apollo-server or in the graphql-tools?
@icebob Yeah, that's not going to work, because you need to have unique names for everything.
If you want, you could probably write a mergeSchemas function which merges different schemas and even namespaces them. It's not that difficult, all you'd have to do is look into the document and produce a new merged one.
Here's a hacky inspiration,
File1.js,
// ----------------------------------------------------------------------- Schema & Resolvers
// ------------------------------------ Schema
const typeShard = `
type Planet {
id: String
name: String
diameter: String
gravity: String
climate: String
terrain: String
rotationPeriod: String
population: String
orbitalPeriod: String
surfaceWater: String
}
`;
const queryShard = `
planets: [Planet]
`;
// ------------------------------------ Resolvers
const resolvers = {
Query: {
planets() {
return API.fetch();
},
},
};
// ----------------------------------------------------------------------- Exports
export { typeShard, queryShard, resolvers };
File2.js
// ----------------------------------------------------------------------- Schema & Resolvers
// ------------------------------------ Schema
const typeShard = `
type SomeOtherType {
id: String
....
}
type RecordsAndMetaData {
records: [SomeOtherType]
totalRecords: String
currentPage: String
}
`;
const queryShard = `
recordsAndMetaData(currentPage: String): RecordsAndMetaData
`;
// ------------------------------------ Resolvers
const resolvers = {
Query: {
recordsAndMetaData(root, { currentPage = '1' } = {}) {
return API.configure({ currentPage });
},
},
RecordsAndMetaData: {
records() {
return API.fetch();
},
},
};
// ----------------------------------------------------------------------- Exports
export { typeShard, queryShard, resolvers };
MergeAndCompileStuff.js
// ----------------------------------------------------------------------- Import stuff
import _ from 'lodash';
// ------------------------------------ Data Emulation
import { typeShard as ts1, queryShard as qs1, resolvers as rs1 } from './location/to/File1.js';
import { typeShard as ts2, queryShard as qs2, resolvers as rs2 } from './location/to/File2.js';
// ----------------------------------------------------------------------- Make stuff
// ------------------------------------ Compile schemas
const compiledSchema = [`
${ts1}
${ts2}
type Query {
${qs1}
${qs2}
}
schema {
query: Query
}
`];
// ------------------------------------ Merge resolvers
const mergedResolvers = {};
_.map([rs1, rs2], function (resolverShard) {
_.map(resolverShard, function (resolvers, outerKey) {
if (mergedResolvers[outerKey] === undefined) {
mergedResolvers[outerKey] = {};
}
_.map(resolvers, function (resolver, innerKey) {
mergedResolvers[outerKey][innerKey] = resolver;
});
});
});
// ----------------------------------------------------------------------- Export stuff
export const thisPackage = 'sandbox:lib-transmit';
export { compiledSchema as schema, mergedResolvers as resolvers };
And in server/start.js,
// ----------------------------------------------------------------------- Imports
// ---------------------------------- Meteor & Apollo
import { Meteor } from 'meteor/meteor';
import { createApolloServer } from 'meteor/apollo';
// ---------------------------------- Fetch Schema & Resolvers for Apollo server
import { schema, resolvers } from 'meteor/sandbox:lib-transmit';
// ----------------------------------------------------------------------- Create Apollo Server
createApolloServer({
graphiql: true,
pretty: true,
schema,
resolvers,
});
// ----------------------------------------------------------------------- Startup code
Meteor.startup(() => {
console.log('hello world!');
});
@dbx834 thanks, your solution will be good.
If there would be namespaces in GraphQL, it solves my problem.
Meanwhile this is my solution to merge schemas & resolvers (similar to @dbx834 solution): https://gist.github.com/icebob/553c1f9f1a9478d828bcb7a08d06790a
I was wondering, whether solution posted by @icebob is still valid in latest Apollo version?
Yes, I'm using with new Apollo version.
Has anyone worked out a more elegant solution to this problem other than joining everything by hand?
It's unrealistic to expect to have all types in the same file.
same inquiry as @PierBover here ...
@PierBover @vmatekole we're having a conversation about schema merging/joining over on another repo, please come join us! https://github.com/apollographql/graphql-prism/issues/1
Thanks @helfer — I will join the conv. Incidentally, I came across this and currently giving it a spin — https://github.com/okgrow/merge-graphql-schemas. I haven't looked under the hood but on first use it appears to fulfil basic merging reqs.
Most helpful comment
@helfer Thanks, but unfortunately it's not solve my problem. My app is modularity, and in every module have queries in the
Query. So I need to merge this queries to one before I gave it to themakeExecutableSchema.For example:
post.module.js
user.module.js
So I need to merge the
Querydefinitions too. InschemaGeneratortheconcatenateTypeDefsfunctions concatenate the typeDefs only.Are there any solution for this problem in the apollo-server or in the graphql-tools?