I would like to inherit resolvers from a graphql interface.
Consider this schema.
const typeDefs = gql`
interface Name {
name: String!
surname: String!
}
type Person implements Name {
_id: ID!
name: String!
surname: String!
}
type Query {
getPerson: Person!
}
}
And these resolvers:
const queryResolver = {
Name: {
name: () => "John",
surname: () => "Doe"
},
Query: {
getPerson: async (parent, args, context, info) => {
return {
_id: "1",
};
},
}
}
This is my server
const { ApolloServer } = require("apollo-server");
const typeDefs = require("./types");
const queryResolvers = require("./resolvers/query");
const resolvers = {
Query: queryResolvers.Query,
Name: queryResolvers.Name,
};
try {
const server = new ApolloServer({
typeDefs,
resolvers,
});
server.listen().then(({ url }) => {
console.log(`Apollo server listening on ${url}`);
});
} catch (e) {
console.error(e);
}
I would like that when querying the server
query Query {
getPerson {
name
surname
}
}
I get John Doe, as I would expect that Person inherits the resolvers from Name.
On ApolloServer v.2 I get this functionality implemented through inheritResolversFromInterfaces https://www.apollographql.com/docs/apollo-server/v2/api/graphql-tools/
I have not been able to find and equivalent on ApolloServer v3.0
The only option I could find is by creating the schema by using makeExecutableSchema from the #graphql-tools/schema, and then passing that schema to the ApolloServer constructor:
const schema = makeExecutableSchema({
typeDefs,
resolvers,
inheritResolversFromInterfaces: true,
});
const server = new ApolloServer({
...otherApolloArguments,
schema,
});
Related
I am trying to setup a GRAND STACK project with a remote neo4j database, the following is the code for the very basic connection:
const { Neo4jGraphQL } = require("#neo4j/graphql");
const neo4j = require("neo4j-driver");
const { ApolloServer } = require("apollo-server");
const typeDefs = `
type Feature {
id: Int
name: String #cypher(statement: "MATCH (n:feature) RETURN n LIMIT 25")
}
type Symptom {
id: Int
name: String #cypher(statement: "MATCH (n:symptom) RETURN n LIMIT 25")
}
type Query {
features: [Feature],
symptoms: [Symptom]
}
`;
const driver = neo4j.driver(
"bolt://serverip:7687",
neo4j.auth.basic("neo4j", "hello-hello-hello")
);
const neoSchema = new Neo4jGraphQL({ typeDefs, driver });
// const resolvers = {
// Query: {
// feature: () => feature,
// },
// };
const server = new ApolloServer({
schema: neoSchema.schema,
context: ({ req }) => ({ req }),
// resolvers
});
server.listen(4000).then(() => console.log("Online"));
And I'm making the following query:
query Query {
symptoms {
name
}
}
The query always returns null. Any help would be greatly appreciated. Thanks.
Neo4j GraphQL autogenerates the queries and mutations for you. In your typeDefs remove the manual queries:
type Query {
features: [Feature]
symptoms: [Symptom]
}
I'm new to GraphQL. I started with the Javascript Apollo library and cannot get a resolver to fire. It's hard for me to tell when resolvers should be called, and what key I should put.
Here's my schema and resolvers:
// The GraphQL schema in string form
const typeDefs = `
type Query { user(id: ID!): User, posts: Post }
type User { id: ID!, created: Int, username: String, bio: String, status: String, avatar: String, posts: [Post] }
type Post { id: ID!, created: Int, user_id: Int, text: String, object_set_id: Int, edited: Int, views: Int, upvotes: Int, downvotes: Int, Parent: Int }
`;
// The resolvers
const resolvers = {
Query: {
user: (parent, args, context, info) => {
return users.find(user => user.id === Number(args.id));
},
// posts: () => posts,
},
Post: {
id: (parent, args, context, info) => {
console.log(posts.filter(post => post.user_id === Number(parent.id)))
return posts.filter(post => post.user_id === Number(parent.id))
}
}
};
I want to specify a user by their user ID, then filter down to get all the posts that user has made (eventually with a time filter).
I've tried several things, but 'posts' under a user always comes up 'null'. What am I missing? Thanks.
User (Or more semantic: userById) query
Your first query works fine.
You should also add some data(Otherwise you get an error "message": "users is not defined",).
Execute query:
query{
user(id: 1){
id
username
}
}
Basic code example:
const { ApolloServer, gql } = require("apollo-server");
const users = [
{
id: 1,
username: "Kate Chopin"
},
{
id: 2,
username: "Paul Auster"
}
];
// The GraphQL schema in string form
const typeDefs = gql`
type Query {
userById(id: ID!): User
}
type User {
id: ID!
username: String
}
`;
// The resolvers
const resolvers = {
Query: {
userById: (parent, args, context, info) => {
return users.find((user) => user.id === Number(args.id));
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
posts query (Or more semantic: postById):
About posts - your query is posts and no resolver match + looks like you do a little "salad" their.
It is better to follow this example (Same idea only books/authors instead of posts/user):
https://www.apollographql.com/docs/apollo-server/getting-started/
Next, read this Resolver chains: https://www.apollographql.com/docs/apollo-server/data/resolvers/#resolver-chains
Again hello world example
const posts = [
{
id: 1,
name: "Article One"
},
{
id: 2,
name: "Article Two"
}
];
const users = [
{
id: 1,
username: "Kate Chopin",
posts: posts
},
{
id: 2,
username: "Paul Auster"
}
];
// The GraphQL schema in string form
const typeDefs = gql`
type Query {
userById(id: ID!): User
}
type User {
id: ID!
username: String
posts: [Post]
}
type Post {
id: ID!
name: String
}
`;
// The resolvers
const resolvers = {
Query: {
userById: (parent, args, context, info) => {
return users.find((user) => user.id === Number(args.id));
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Query:
I'm trying to make a findOneByEmail/id for graphQL. I saw a couple of questions, blog posts, and videos, but they didn't help my case. I know I have to add a filter, but I have to be missing something
Here are my resolvers
const users = [
{id: 1, email:'a#a.a',password:'zaq1#WSX', pons:[{value:'test'}]},
{id: 2, email:'b#b.b',password:'ZAQ!2wsx', pons:[{value:'tset'}]}
];
const pons = [{value: 'test'}];
module.exports = {
Query: {
users: () => users,
pons: () => pons,
}
};
typeDefs
const {gql} = require('apollo-server-express');
module.exports = gql`
type Pon {
value: String!
}
type User {
id: Int
email: String!
password: String!
pons: [Pon]!
}
type Query {
findUser(id: Int): [User]
users: [User]
pons: [Pon]
}
`;
app.js
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const typeDefs = require('./graphql/typeDefs.js');
const resolvers = require('./graphql/resolvers.js');
const server = new ApolloServer({typeDefs, resolvers});
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);
I am using express with apollo-server-express.
I tried adding users(id: Int) and users(email: String), but with no success. You can see it in findUser query. I am calling the query like:
query{
findUser(id: 1) {
email
pons {
value
}
}
}
In the GQL playground.
I'd like to able to filter the data on the server, not on the client, and can't find the solution anywhere
You can get the id parameters in GraphQL resolver and query user by it.
E.g.
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { gql } = require('apollo-server-express');
const users = [
{ id: 1, email: 'a#a.a', password: 'zaq1#WSX', pons: [{ value: 'test' }] },
{ id: 2, email: 'b#b.b', password: 'ZAQ!2wsx', pons: [{ value: 'tset' }] },
];
const pons = [{ value: 'test' }];
const typeDefs = gql`
type Pon {
value: String!
}
type User {
id: Int
email: String!
password: String!
pons: [Pon]!
}
type Query {
findUser(id: Int): User
users: [User]
pons: [Pon]
}
`;
const resolvers = {
Query: {
users: () => users,
pons: () => pons,
findUser: (_, { id }) => users.find((u) => u.id === id),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () => console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`));
query in GraphQL playground:
query{
findUser(id: 1){
email
pons {
value
}
}
}
response:
{
"data": {
"findUser": {
"email": "a#a.a",
"pons": [
{
"value": "test"
}
]
}
}
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I need a list of files in folder, returned with GraphQL query. Can someone explain, how to configure the type and resolver the list? I have some configuration with fs() method, but it doesn't return the list of files. There's a code of schema and resolvers below. To shorten the code, I removed some resolvers that are not related to files.
Will be very grateful for any help!
schema.js
const { buildSchema } = require('graphql');
module.exports = buildSchema(`
type Hero {
_id: ID!
title: String!
description: String
date: String!
}
type File {
path: String
}
input HeroInput {
title: String!
description: String!
date: String!
}
input HeroUpdate {
_id: ID!
title: String!
description: String
date: String!
}
input HeroRemove {
_id: ID!
}
type RootQuery {
heroes: [Hero!]!
findHero(id: ID!): Hero
files: File
}
type RootMutation {
createHero(heroInput: HeroInput): Hero
deleteHero(heroRemove: HeroRemove): Hero
updateHero(heroUpdate: HeroUpdate): Hero
}
schema {
query: RootQuery
mutation: RootMutation
}
`);
resolvers.js
const Hero = require('./models/hero');
const path = require('path');
const fs = require('fs');
module.exports = {
files: () => {
const filesPath = path.join(__dirname, './files');
return fs.readdir(filesPath, function (err, files) {
if (err) {
return console.log('Unable to scan directory: ' + err);
}
console.log(files);
return files.map(file => {
return {
path: file
};
});
});
},
heroes: () => {
return Hero.find()
.then(heroes => {
return heroes.map(hero => {
return {
...hero._doc,
_id: hero.id,
date: new Date(hero.date).toISOString()
};
});
})
.catch(err => {
throw err;
});
}
};
Your files resolver does not work as expected because you are returning fs.readdir. However, the function is asynchronous and therefore immediately returns undefined instead of the result of your callback function.
To avoid this problem you could use fs.readdirSync instead of fs.readdir:
files: () => {
const filesPath = path.join(__dirname, './files');
const files = fs.readdirSync(filesPath);
return files.map(file => ({path: file}));
}
Note: I used a shorthand notation for the map function in order to immediately return the object!
Documentation of fs.readdirSync: https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options
Hope this solved your problem :)
Cheers,
derbenoo
The solution is to configure the File type and query in schema.js
const { buildSchema } = require('graphql');
module.exports = buildSchema(`
type Hero {
_id: ID!
title: String!
description: String
date: String!
}
type File {
path: String
}
input HeroInput {
title: String!
description: String!
date: String!
}
input HeroUpdate {
_id: ID!
title: String!
description: String
date: String!
}
input HeroRemove {
_id: ID!
}
type RootQuery {
heroes: [Hero!]!
findHero(id: ID!): Hero
files: [File]
}
type RootMutation {
createHero(heroInput: HeroInput): Hero
deleteHero(heroRemove: HeroRemove): Hero
updateHero(heroUpdate: HeroUpdate): Hero
}
schema {
query: RootQuery
mutation: RootMutation
}
`);
I'm new in graphql and I am trying to integrate an authentication/authorization system in my project. I found an example on Medium, but I do not understand how a guard communicates with a resolver. If someone knows, I will be very grateful.
import { ApolloServer } from 'apollo-server';
import gql from 'graphql-tag';
import { tradeTokenForUser } from './auth-helpers';
const HEADER_NAME = 'authorization';
const typeDefs = gql`
type Query {
me: User
serverTime: String
}
type User {
id: ID!
username: String!
}
`;
const resolvers = {
Query: {
me: authenticated((root, args, context) => context.currentUser),
serverTime: () => new Date(),
},
User: {
id: user => user._id,
username: user => user.username,
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
let authToken = null;
let currentUser = null;
try {
authToken = req.headers[HEADER_NAME];
if (authToken) {
currentUser = await tradeTokenForUser(authToken);
}
} catch (e) {
console.warn(`Unable to authenticate using auth token: ${authToken}`);
}
return {
authToken,
currentUser,
};
},
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
export const authenticated = next => (root, args, context, info) => {
if (!context.currentUser) {
throw new Error(`Unauthenticated!`);
}
return next(root, args, context, info);
};
I do not understand what "next" parameter does and why as an argument when this guard is called I have to return a value?
authenticated is higher-order function that makes the code DRY. next is a callback that is used as a predicate.
It's a DRYer way to write:
...
me: (root, args, context) => {
if (!context.currentUser) {
throw new Error(`Unauthenticated!`);
}
return context.currentUser;
)
...