Apollo GraphQL cannot query _service - node.js

I'm new in GraphQL. When I copied this code from Apollo GraphQL docs (and just add one more line for console.log error), I have this issue. Please let me know how to fix it.
const { ApolloServer, gql } = require('apollo-server-express');
const express = require('express');
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{
title: 'The Awakening',
author: 'Kate Chopin',
},
{
title: 'City of Glass',
author: 'Paul Auster',
},
];
const resolvers = {
Query: {
books: () => books,
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (err) => console.log(err), // <-- only add 1 more line
});
(async () => {
const app = express();
await server.start();
server.applyMiddleware({ app });
app.listen(4000);
})();
And here is my package.json
"dependencies": {
"apollo-server-express": "^3.6.3",
"express": "^4.17.2",
"graphql": "^16.3.0"
}
Then, when I open graphql studio playground at http://localhost:4000/graphql -> click on Query your server -> I got this error on terminal
[ValidationError: Cannot query field "_service" on type "Query".] {
locations: [ { line: 2, column: 9 } ],
path: undefined,
extensions: {
code: 'GRAPHQL_VALIDATION_FAILED',
exception: { stacktrace: [Array] }
}
}```

I have checked again and this is an error from inside GrapqhQL Studio and it was fixed now.

Related

How can I add dig into errors on grahpql subscription over websocket?

I setup a graphql server and client by Apollo in nodejs. The server will serve one http link for query and mutation and one websocket link for subscription.
When I run the code, query and mutation works fine but subscription doesn't work. The server doesn't see any subscription request but the client doesn't throw any errors.
I am not sure what I am doing is wrong. How can I see detailed information on websocket layer?
Server code:
const { ApolloServer } = require('#apollo/server');
const { makeExecutableSchema } = require('#graphql-tools/schema');
const { createServer } = require('http');
const express = require('express');
const { WebSocketServer } = require('ws');
const { ApolloServerPluginDrainHttpServer } = require('#apollo/server/plugin/drainHttpServer');
const { useServer } = require('graphql-ws/lib/use/ws');
const cors = require('cors');
const bodyParser = require('body-parser');
const { expressMiddleware } = require('#apollo/server/express4');
const { PubSub } = require('graphql-subscriptions');
const typeDefs = `#graphql
type Book {
title: String
author: String
}
input BookInput {
title: String
author: String
}
type Query {
books: [Book]
}
type Subscription {
bookCreated: Book
}
type Mutation {
postBook(input: BookInput): ID!
}
`;
const pubsub = new PubSub();
const resolvers = {
Query: {
books: () => [
{
title: 'hello',
author: 'joey',
},
],
},
Subscription: {
bookCreated: {
subscribe: () => {
console.log('receive subscribe');
pubsub.asyncIterator(['POST_CREATED']);
},
},
},
Mutation: {
postBook: async (book) => {
console.log('postBook', book)
await pubsub.publish('POST_CREATED', {
postCreated: {
title: 'Ali Baba',
author: 'Open sesame',
},
});
return '001';
},
},
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const app = express();
const httpServer = createServer(app);
const wsServer = new WebSocketServer({
server: httpServer,
path: '/graphql',
});
const serverCleanup = useServer({ schema }, wsServer);
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
server.start().then((d) => {
console.log('started', d);
app.use('/graphql', cors(), bodyParser.json(), expressMiddleware(server));
});
httpServer.listen(4000, () => {
console.log(`Server is now running on http://localhost:4000/graphql`);
});
client code:
const { ApolloClient } = require('apollo-client');
const { InMemoryCache } = require('apollo-cache-inmemory');
const gql = require('graphql-tag');
const { createHttpLink } = require('apollo-link-http');
const ws = require('ws');
const { SubscriptionClient } = require('subscriptions-transport-ws');
const { WebSocketLink } = require('apollo-link-ws');
const fetch = require('node-fetch');
const httpLink = createHttpLink({
uri: `http://localhost:4000/graphql`,
fetch,
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
});
const wsLink = new WebSocketLink(
new SubscriptionClient(
'ws://localhost:4000/graphql',
{
reconnect: true,
},
ws,
[]
)
);
const wsclient = new ApolloClient({
link: wsLink,
cache: new InMemoryCache(),
});
client
.query({
query: gql`
query books {
books {
author
}
}
`,
})
.then((result) => console.log(JSON.stringify(result, null, 2)));
wsclient
.subscribe({
query: gql`
subscription bookCreated {
bookCreated {
author
}
}
`,
})
.subscribe({
next: (d) => {
console.log('subscirbe', d);
},
error: (err) => console.error(err),
});
setTimeout(() => {
client
.mutate({
mutation: gql`
mutation postBook {
postBook(input: { author: "aa", title: "title" })
}
`,
})
.then((d) => console.log('mutate:', d))
.catch(console.error);
}, 1000);

Missing multipart field ‘operations’ with graphql-upload and apollo-server

Hello I am trying to upload a file using graphql in order to do this I have the following code:
index.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const { graphqlUploadExpress } = require('graphql-upload');
async function startApolloServer() {
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
Mutation: {
singleUpload: async (parent, { file }) => {
const { createReadStream, filename, mimetype, encoding } = await file;
const stream = createReadStream();
const out = require('fs').createWriteStream(filename);
stream.pipe(out);
return { filename, mimetype, encoding, url: '' }
}
}
};
const server = new ApolloServer({
typeDefs:gql`
type Query {
hello: String!
}
type UploadedFileResponse {
filename: String!
mimetype: String!
encoding: String!
url: String!
}
type Mutation {
singleUpload(file: Upload!): UploadedFileResponse!
}`
, resolvers },{uploads:false});
await server.start();
const app = express();
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
server.applyMiddleware({ app });
await new Promise(resolve => app.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}
startApolloServer()
And in order to call the endpoint I am using the following curl:
curl localhost:4000/graphql \
-F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { filename } }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=#/home/user/a.txt
But when I execute this I got the following error:
Missing multipart field ‘operations’
If I remove app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
I got another error
function deprecated(...args) {
RangeError: Maximum call stack size exceeded
But in this case I can write a empty file with the correct name.
Any idea about how can I finish this poc in order to upload a file using apollo-graphql.
Package.json
"dependencies": {
"apollo-server": "^2.25.2",
"apollo-server-express": "^2.25.2",
"graphql": "^15.5.1",
"graphql-upload": "^12.0.0"
},
"devDependencies": {
"nodemon": "^2.0.12"
},
But I tried whit this too
"resolutions": {
"**/**/fs-capacitor": "^6.2.0",
"**/graphql-upload": "^11.0.0"
}
Node version: 14.16.1 and 14.17.3
Thanks
In your typDefs, add: scalar Upload
In resolvers, add: Upload: GraphQLUpload
GraphQLUpload is imported from 'graphql-upload': import { GraphQLUpload } from "graphql-upload";

Using express as middleware in apollo server leads to JSON parse error

I'm creating an application where I'm using graphql and react native alongside apollo. When my server code is not using express, I'm able to successfully query from the server using
import { useQuery } from '#apollo/react-hooks';
However, I require express to be able to add a middleware and authenticate users. This throws a: Error! Network error: JSON Parse error: Unrecognized token '<'
Works with this code below (without express)
const { ApolloServer, gql } = require('apollo-server');
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{
title: 'Harry Potter and the Chamber of Secrets',
author: 'J.K. Rowling',
},
{
title: 'Jurassic Park',
author: 'Michael Crichton',
},
];
const resolvers = {
Query: {
books: () => books,
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen({ port:4000 }, () => {
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
});
-
Whereas this code below throws an error
const { ApolloServer, gql } = require('apollo-server-express')
const express = require('express');
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{
title: 'Harry Potter and the Chamber of Secrets',
author: 'J.K. Rowling',
},
{
title: 'Jurassic Park',
author: 'Michael Crichton',
},
];
const resolvers = {
Query: {
books: () => books,
},
};
const app = express();
const server = new ApolloServer({ typeDefs, resolvers });
server.applyMiddleware({ app, path: '/graphql' });
app.listen({ port:4000 }, () => {
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
});
If this is a parse issue, how do I correctly parse the data? I've tried
app.use(bodyParser.json())
app.use(bodyParser.raw())
app.use(bodyParser.urlencoded())
app.use(bodyParser.text())
however this doesn't seem to help :/
Any ideas?

graphql subscriptions with child nodes seems not working for me

First of all, Subscriptions is working if I have next code structure
schema
type Subscription {
somethingChanged: IResult
}
type IResult {
id: String!
}
resolvers
export const resolvers = {
Query: {
},
Mutation: {
},
Subscription: {
somethingChanged: {
subscribe: () => pubSub.asyncIterator(SOMETHING_CHANGED_TOPIC)
}
},
};
The problem became be a problem when I try to make somethingChanged node as a child of another account node, like so:
So next schema and resolvers are not working
type Subscription {
account(token: String!): IAccountAction
}
type IResult {
id: String!
}
type IAccountAction {
somethingChanged: IResult
}
export const resolvers = {
Query: {
},
Mutation: {
},
Subscription: {
account: (root: any, token: string) => ({
somethingChanged: {
subscribe: () => pubSub.asyncIterator(SOMETHING_CHANGED_TOPIC)
}
})
},
};
ERROR
{
"error": {
"message": "Subscription field must return Async Iterable. Received: undefined"
}
}
I believe that is not an issue and only misunderstanding )) Please help me ))
Additional info which might help:
server.ts
import {resolvers} from './generated/resolvers';
import {typeDefs} from './generated/mergedGQLSchemas';
import http from 'http';
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const PORT = 4001;
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
});
server.applyMiddleware({
app
});
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
httpServer.listen(PORT, () => {
console.log(`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`);
console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
});

server.register() function throwing "register is missing", even though i have properly registered the plugins for graphql

I have created a node js project with graph ql (with a very basic schema) but when i am trying to start the server after registering the plugins for graphql and graphiql, i am getting the register is missing error. Below is my code
const hapi=require('hapi');
const { graphqlHapi, graphiqlHapi } = require('apollo-server-hapi');
const { makeExecutableSchema } = require('graphql-tools');
const graphqlSchema = require('./graphql/schema');
const createResolvers = require('./graphql/resolvers');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
const server=hapi.server({
port: 4000,
host:'localhost'
});
server.register({
plugin: graphqlHapi,
options: {
path: '/graphql',
graphqlOptions: () => ({
pretty: true,
schema: executableSchema,
}),
},
});
server.register({
plugin: graphiqlHapi,
options: {
path: '/graphiql',
graphiqlOptions: {
endpointURL: '/graphql',
},
},
});
const init= async()=>{
routes(server);
await server.start();
console.log(`Server is running at: ${server.info.uri}`);
}
init();
I had initially given the key name as register instead of plugin in the server.register() functions. In either case, i am getting the below error
(node:19104) DeprecationWarning: current URL string parser is
deprecated, and will be removed in a future version. To use the new
parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(node:19104) UnhandledPromiseRejectionWarning: AssertionError
[ERR_ASSERTION]: I nvalid plugin options {
"plugin": {
"options": {
"path": "/graphql",
"graphqlOptions": () => ({\r\n pretty: true,\r\n schema: exe cutableSchema,\r\n })
},
"register" [1]: -- missing -- } }
Please help me out in understanding whenter code herey this happening and how it can be rectified.
Below is the dependencies in my project
apollo-server-hapi": "^2.3.1", "graphql": "^14.0.2", "graphql-tools":
"^4.0.3", "hapi": "^17.8.1",
EDIT
Code after making the suggested changes
const hapi=require('hapi');
const { graphqlHapi, graphiqlHapi } = require('apollo-server-hapi');
const { makeExecutableSchema } = require('graphql-tools');
const graphqlSchema = require('./graphql/schema');
const createResolvers = require('./graphql/resolvers');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
async function start_server() {
const server=hapi.server({
port: 4000,
host:'localhost'
});
await server.register({
plugin: graphqlHapi,
options: {
path: '/graphql',
graphqlOptions: () => ({
pretty: true,
schema: executableSchema,
}),
route: {
cors: true,
},
},
});
await server.register({
plugin: graphiqlHapi,
options: {
path: '/graphiql',
graphiqlOptions: {
endpointURL: '/graphql',
},
route: {
cors: true,
},
},
});
try {
await server.start();
console.log(`Server is running at: ${server.info.uri}`);
} catch (err) {
console.log(`Error while starting server: ${err.message}`)
}
}
start_server();
There is no need to register the plugins in the latest release of apollo-server-hapi. It contains GraphQL playground instead of graphiql.
The below changes need to be done instead of registering.
const {ApolloServer} = require('apollo-server-hapi');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
const server = new ApolloServer({
schema:executableSchema
});
async function start_server() {
const app=hapi.server({
port: 4000,
host:'localhost'
});
await server.applyMiddleware({ app });
try {
await app.start();
console.log(`Server is running at: ${app.info.uri}`);
} catch (err) {
console.log(`Error while starting server: ${err.message}`)
}
}
start_server();

Resources