At this instance i am just trying to run a dummy subscription using graphql-subscriptions, and later-on, integrate it in my code.
However, even with the minimal example.
I am following a scotch.io example, here is its git link
https://github.com/kimobrian/GraphQL-Express/tree/subscriptions
it is throwing error on subscription at graphiql
subscriptionsClient.subscribe is not a function
Note: I am not even trying it from a separate client. I just want a server that has schema including queries and mutations and subscription, and i want to be able to see the real-time magic of subscription when i run it in graphiql in different windows.
Following some suggestions on the net, i have even downgraded subscription-transport-ws version from 0.9 to 0.8.3
I have running queries and mutations but subscription throws above mentioned error in Graphiql
Server File
import express from 'express';
import {
graphqlExpress,
graphiqlExpress,
} from 'graphql-server-express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { schema } from './src/schema';
import { execute, subscribe } from 'graphql';
import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
const PORT = 7900;
const server = express();
server.use('*', cors({ origin: 'http://localhost:3000' }));
server.use('/graphql', bodyParser.json(), graphqlExpress({
schema
}));
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://localhost:${PORT}/subscriptions`
}));
// We wrap the express server so that we can attach the WebSocket for subscriptions
const ws = createServer(server);
ws.listen(PORT, () => {
console.log(`GraphQL Server is now running on http://localhost:${PORT}`);
// Set up the WebSocket for handling GraphQL subscriptions
new SubscriptionServer({
execute,
subscribe,
schema
}, {
server: ws,
path: '/subscriptions',
});
});
package.json
{
"name": "tutorial-server",
"version": "1.0.0",
"description": "A simple GraphQL server",
"main": "server.js",
"scripts": {
"start": "nodemon ./server.js --exec babel-node -e js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"babel-preset-stage-0": "^6.22.0",
"nodemon": "^1.11.0"
},
"dependencies": {
"body-parser": "^1.17.1",
"cors": "^2.8.3",
"express": "^4.15.2",
"graphql": "^0.11.3",
"graphql-server-express": "^1.1.2",
"graphql-subscriptions": "^0.5.1",
"graphql-tools": "^1.2.3",
"subscriptions-transport-ws": "0.8.3"
}
}
Schema
import {
makeExecutableSchema
} from 'graphql-tools';
import { resolvers } from './resolvers';
const typeDefs = `
type Channel {
id: ID! # "!" denotes a required field
name: String
}
type Message {
id: ID!
text: String
}
# This type specifies the entry points into our API
type Query {
channels: [Channel] # "[]" means this is a list of channels
channel(id: ID!): Channel
}
# The mutation root type, used to define all mutations
type Mutation {
addChannel(name: String!): Channel
}
# The subscription root type, specifying what we can subscribe to
type Subscription {
channelAdded: Channel
}
`;
const schema = makeExecutableSchema({ typeDefs, resolvers });
export { schema };
Resolver
import { PubSub } from 'graphql-subscriptions';
const channels = [{
id: 1,
name: 'soccer',
}, {
id: 2,
name: 'baseball',
}];
let nextId = 3;
const CHANNEL_ADDED_TOPIC = 'newChannel';
const pubsub = new PubSub();
export const resolvers = {
Query: {
channels: () => {
return channels;
},
channel: (root, { id }) => {
return channels.find(channel => channel.id === id);
},
},
Mutation: {
addChannel: (root, args) => {
const newChannel = { id: String(nextId++), messages: [], name: args.name };
channels.push(newChannel);
pubsub.publish(CHANNEL_ADDED_TOPIC, { channelAdded: newChannel });
return newChannel;
}
},
Subscription: {
channelAdded: {
subscribe: () => pubsub.asyncIterator(CHANNEL_ADDED_TOPIC)
}
}
};
I expect that it should update in the subscription window when pubsub.publish is hit
Related
I have this code and i try to charge the subscription in apollo playground but i cant it, I also tried to import 'PubSub' from apollo-server but this didn't work, I also tried to follow the documentation but it gave the same result, I have been reading in many places but no solutions; I must emphasize that the subscriptionsUrl returns me undefined and according to what I investigate it should be something like 'ws://...',
not if my code is a bit old or what happens
i'm trying make the subscription executed in loop but i receive the response
{
"message": "server must support graphql-ws or subscriptions-transport-ws protocol"
}
the typeDefs and resolvers is declared in the same file that server variable, does anyone know what to do?
import * as dotenv from 'dotenv'
dotenv.config()
import './mongo.js'
import {
ApolloServer,
AuthenticationError,
gql,
UserInputError
} from 'apollo-server'
import { PubSub } from 'graphql-subscriptions'
import Person from './models/person.js'
import User from './models/user.js'
import jwt from 'jsonwebtoken'
const { JWT_SECRET } = process.env
const SUBS_EVENTS = {
PERSON_ADDED: 'PERSON_ADDED'
}
const pubsub = new PubSub()
const typeDefs = gql`...`
const resolvers = {...}
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
const auth = req ? req.headers.authorization : null
if (auth && auth.toLowerCase().startsWith(`bearer `)) {
const token = auth.substring(7)
const { id } = jwt.verify(token, JWT_SECRET)
const currentUser = await User.findById(id).populate('friends')
return { currentUser }
}
}
})
server.listen().then(({ url, subscriptionsUrl }) => {
console.log(`Server ready at ${url}`)
console.log(`Subscriptions ready at ${subscriptionsUrl}`)
})
// in the json
{
"name": "graphql-server",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "index.js",
"scripts": {
"jsonserver": "json-server --watch db.json",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server": "3.10.3",
"axios": "1.1.3",
"dotenv": "16.0.3",
"express": "^4.18.2",
"graphql": "^16.6.0",
"graphql-subscriptions": "^2.0.0",
"jsonwebtoken": "8.5.1",
"mongoose": "6.7.0",
"mongoose-unique-validator": "3.1.0",
"uuid": "9.0.0"
},
"devDependencies": {
"json-server": "0.17.0"
}
}
I am getting this message POST body missing, invalid Content-Type, or JSON object has no keys when using the Test/Run options in the code editor of Azure.
Here is my Typescript code that works locally fine but not when running through the Azure portal. Where should I make the changes to make it work on the Azure portal?
import { ApolloServer, gql } from "apollo-server-azure-functions"
const quizzes = [
{
id: '1',
question: 'Hobbies',
correctAnswer: 'Technology'
}
];
const typeDefs = gql`
type Quiz {
id: String!
question: String!
correctAnswer: String!
}
type Query {
quizzes: [Quiz!]!
quiz(id: String!): Quiz!
}
type Mutation {
createQuestionInput(id: ID!, question: String!, correctAnswer: String!): Quiz
}
`
const resolvers = {
Query : {
quizzes: async (parent, args, context, info) => {
return quizzes;
},
quiz: async (parent, args, context, info) => {
return quizzes.find((quiz) => quiz.id == args.id);
}
},
Mutation: {
createQuestionInput: async(parent, args, context, info) => {
quizzes.push({id: args.id,
question: args.question,
correctAnswer: args.correctAnswer});
return quizzes.find((quiz)=> quiz.id ==args.id);
}
}
}
const server = new ApolloServer({ typeDefs, resolvers})
export default server.createHandler();
function.json
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post",
"options"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
],
"scriptFile": "../dist/graphql-sumesh-fn/index.js"
}
i'm having a hard time figuring out the problem with my setup. I have been looking at the documentations but between apollo and graphql-tools the APIs changed frequently.
When i run this script, the console says "Error: Query root type must be provided."
import { ApolloServer } from "apollo-server";
import { loadSchema } from "#graphql-tools/load";
import { UrlLoader } from "#graphql-tools/url-loader";
import { stitchSchemas } from "#graphql-tools/stitch";
import fetch from "node-fetch";
import dotenv from "dotenv";
dotenv.config({ path: "../.env" });
async function startServer() {
const shopifySchema = await loadSchema(process.env.SHOPIFY_STOREFRONT_URL, {
loaders: [new UrlLoader()],
headers: {
"X-Shopify-Storefront-Access-Token":
process.env.SHOPIFY_STOREFRONT_API_TOKEN,
},
fetch,
});
const contentfulSchema = await loadSchema(process.env.CONTENTFUL_API_URL, {
loaders: [new UrlLoader()],
headers: {
Authorization: `Bearer ${process.env.CONTENTFUL_API_TOKEN}`,
},
fetch,
});
const gatewaySchema = stitchSchemas({
subschemas: [{ schema: shopifySchema }, { schema: contentfulSchema }],
});
const server = new ApolloServer({ schema: gatewaySchema });
return await server.listen();
}
startServer().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
These are my dependencies:
{
"#graphql-tools/load": "^7.3.2",
"#graphql-tools/schema": "^8.2.0",
"#graphql-tools/stitch": "^8.3.1",
"#graphql-tools/url-loader": "^7.2.0",
"apollo-server": "^3.4.0",
"dotenv": "^10.0.0",
"graphql": "^15.6.1",
"node-fetch": "^3.0.0"
}
Anyone knows what could be wrong with this?
Ok, i have found out that my url endpoints were just incorrect.
I'll leave the question open in case might be useful to someone.
I have a component that passes a string (userToFetch) it as a variable parameter in a parameterized query. The component looks like this:
// pages/index.jsx
import React from 'react';
import { useQuery } from '#apollo/react-hooks';
import gql from 'graphql-tag';
const GET_USERS = gql`
query users ($limit: Int!, $username: String!) {
users (limit: $limit, where: { username: $username }) {
username
firstName
}
}
`;
const Home = () => {
const userToFetch = 'jonsnow';
const {
loading,
error,
data,
} = useQuery(
GET_USERS,
{
variables: { limit: 2, username: userToFetch },
notifyOnNetworkStatusChange: true,
},
);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {JSON.stringify(error)}</p>;
}
return (
<div>
<ul>
{data.users.map(user => {
return <li>{user.username} {user.firstName}</li>;
})}
</ul>
</div>
);
};
export default Home;
And this is how I have configured my Apollo client:
// /apollo-client.js
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import withApollo from 'next-with-apollo';
import { createHttpLink } from 'apollo-link-http';
import fetch from 'isomorphic-unfetch';
const GRAPHQL_URL = 'https://dev.schandillia.com/graphql';
const link = createHttpLink({
fetch, // Switches between unfetch & node-fetch for client & server.
uri: GRAPHQL_URL
});
// Export a HOC from next-with-apollo
// Docs: https://www.npmjs.com/package/next-with-apollo
export default withApollo(
// You can get headers and ctx (context) from the callback params
// e.g. ({ headers, ctx, initialState })
({ initialState, ctx }) => {
console.log('initialState', initialState);
console.log('ctx', ctx);
return new ApolloClient({
link: link,
cache: new InMemoryCache()
// rehydrate the cache using the initial data passed from the server:
.restore(initialState || {})
})
}
);
The database is a collection of following users:
"users": [
{
"username": "negger",
"firstName": "Arnold",
"lastName": "Schwarzenegger"
},
{
"username": "jonsnow",
"firstName": "Jon",
"lastName": "Snow"
},
{
"username": "tonystark",
"firstName": "Tony",
"lastName": "Stark"
}
]
}
Now, although this should work (it does when I run the query in my graphql playground at https://dev.schandillia.com/graphql), the code runs as if the where clause didn't exist! It just returns all results as if the query being run were:
users {
_id
username
firstName
}
In order to reproduce the issue, visit https://www.schandillia.com. The page ought to display a list with only one element consisting of a matching username-firstName value: jonsnow Jon but it returns two entries, negger Arnold and jonsnow Jon (respecing limit but completely ignoring where). Now, run the same query with jonsnow as a where parameter in https://dev.schandillia.com/graphql:
{
users(where: { username: "jonsnow" }) {
_id
username
firstName
}
}
And the results would be exactly as expected:
{
"data": {
"users": [
{
"_id": "5d9f261678a32159e61018fc",
"username": "jonsnow",
"firstName": "Jon",
}
]
}
}
What am I overlooking?
P.S.: The repo is up for reference at https://github.com/amitschandillia/proost/tree/master/apollo-nextjs.
UPDATE: In order to track down the root cause, I tried logging some values in apollo-client.js:
console.log('initialState', initialState);
Strangely, the output shows the right query, along with the variables being passed, but wrong results:
...
ROOT_QUERY.users({"limit":2,"where":{"username":"jonsnow"}}).0:
firstName: "Arnold"
username: "negger"
__typename: "UsersPermissionsUser"
...
UPDATE: Here's a screenshot of results in my Apollo Client Developer Tools:
The schema generated by Strapi gives the where attribute a Type JSON and hence you have to pass the entire where part in the query variable as JSON since the variables are not getting injected.
# Write your query or mutation here
query users($where: JSON) {
users(where: $where) {
username
firstName
}
}
And the variables would look like:
{"where": {"username": "jonsnow"}}
I'm following the Full Stack Tutorial for Apollo and whenever I try to add dataSources to my Apollo Server, the playground throws a 500 error with no additional data to debug with.
I've tried adding introspection to true, I removed everything babel related, completely redid my imports so everything is in proper format.
If I comment out dataSources, it works fine, even when providing an empty function, it fails.
Please help me, this is killing me!
index.js
const {ApolloServer} = require('apollo-server');
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const BreweryAPI = require('./datasources/brewery');
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {},
introspection: true
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
schema.js
const {gql} = require('apollo-server');
const typeDefs = gql`
type Query {
breweries: [Brewery]!
#Get a brewery by ID
brewery(id: ID!): Brewery
#Get a brewery by name
breweriesByName(name: String!): [Brewery]
#Get a list of breweries by state
breweriesByState(state: String!): [Brewery]
#Get a list of breweries by tag
breweriesByTag(tag: String!): [Brewery]
}
type Brewery {
id: ID!
name: String
type: String
street: String
city: String
state: String
postal: String
country: String
latitude: String
longitude: String
phone: String
url: String
tags: [String]
}
type User {
id: ID!
email: String!
favorites: [Brewery]
visited: [Brewery]
beers: Int
}
type RequestResponse {
errors: [String]
success: Boolean
}
type Mutation {
#Add a favorite brewery
addFavorite(id: ID!): RequestResponse
#Remove a favorite brewery
removeFavorite(id: ID!): RequestResponse
#Add a visited brewery
addVisited(id: ID!): RequestResponse
#Add number of beers drank at brewery
addBeers(beers: Int!): Int
#Login to track your alcoholism
login(email: String): String
}
`;
module.exports = typeDefs;
resolvers.js
module.exports = {
Query: {
breweries: async (_, __, { dataSources }) => dataSources.breweryAPI.getAllBreweries()
}
}
package.json
{
"name": "fullstack-tutorial-server",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "jest",
"start": "node src/index.js",
"start:ci": "node src/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"apollo-datasource": "^0.1.3",
"apollo-datasource-rest": "^0.1.5",
"apollo-server": "2.2.0-alpha.2",
"apollo-server-testing": "2.2.0-alpha.2",
"axios": "^0.18.0",
"graphql": "^14.0.2",
"isemail": "^3.1.3",
"nodemon": "^1.18.4",
"sequelize": "^4.39.0",
"sqlite3": "^4.0.3"
},
"devDependencies": {
"apollo-link": "^1.2.3",
"apollo-link-http": "^1.5.5",
"jest": "^23.6.0",
"nock": "^10.0.2",
"node-fetch": "^2.2.1"
},
"jest": {
"testPathIgnorePatterns": [
"/node_modules/",
"/__utils"
]
}
}
I have no idea whats left to try at this point and there are no other questions available to research on stackoverflow
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {},
introspection: true
});
Should be
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => ({}),
introspection: true
});
Weird syntax but it causes the error mentioned, no idea why!