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"
}
}
Related
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 create a project base on with-ant-design-less and then try to add sass to project. I change the following files:
next.config.js:
/* eslint-disable */
const withSass = require("#zeit/next-sass");
const withLess = require("#zeit/next-less");
const lessToJS = require("less-vars-to-js");
const fs = require("fs");
const path = require("path");
// Where your antd-custom.less file lives
const themeVariables = lessToJS(
fs.readFileSync(path.resolve(__dirname, "./assets/antd-custom.less"), "utf8")
);
module.exports = withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
localIdentName: "[folder]_[local]___[hash:base64:5]",
},
...withLess({
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables, // make your antd custom effective
},
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === "function") {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === "function" ? [] : origExternals),
];
config.module.rules.unshift({
test: antStyles,
use: "null-loader",
});
}
return config;
},
}),
});
package.json
{
"name": "with-ant-design-less",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"#zeit/next-less": "^1.0.1",
"#zeit/next-sass": "^1.0.1",
"antd": "^3.5.4",
"babel-plugin-import": "^1.7.0",
"less": "3.0.4",
"less-vars-to-js": "1.3.0",
"next": "latest",
"null-loader": "2.0.0",
"react": "^16.7.0",
"sass": "^1.26.3",
"react-dom": "^16.7.0"
},
"license": "ISC",
"devDependencies": {
"#types/node": "^13.13.1",
"typescript": "^3.8.3"
}
}
but when I run the project I get the following error:
[ error ] ./pages/index.module.scss
To use Next.js' built-in Sass support, you first need to install `sass`.
Run `npm i sass` or `yarn add sass` inside your workspace.
Although I'm looking for better solution to setup the project because in this way all the style will be in one big chunk that cause performance issue.
Any idea? Thanks
next.config.js:
const withPlugins = require('next-compose-plugins');
const withCss = require('#zeit/next-css');
const withSass = require('#zeit/next-sass');
const withLess = require('#zeit/next-less');
const lessToJS = require('less-vars-to-js');
const fs = require('fs');
const path = require('path');
const lessThemeVariablesFilePath = './static/ant-theme-variables.less';
const themeVariables = lessToJS(
fs.readFileSync(path.resolve(__dirname, lessThemeVariablesFilePath), 'utf8'),
);
const lessNextConfig = {
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables,
},
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
});
}
return config;
},
};
const sassNextConfig = {
cssModules: true,
cssLoaderOptions: {
localIdentName: '[path]___[local]___[hash:base64:5]',
},
};
module.exports = withPlugins([
[withLess, lessNextConfig],
[withSass, sassNextConfig],
]);
babel config:
module.exports = {
presets: ['next/babel'],
plugins: [
['import', { libraryName: 'antd', style: true }],
],
};
I use sass, less and css. it depends on your requirement. and you can add your custom variables in an static file as I did.
hope be helpful.
So, for people who came here just for the basic addition, you can add antd to your nextjs app by installing antd
npm i antd
and then you can add the antd styles to your
_app.js file
after your global styles:
import 'antd/dist/antd.css'
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
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!
I use babel-eslint to lint/fix my code. Worked great until I wanted to adopt some ES2017 async await found overhere.
I changed my React app accordingly, allbeit slightly different:
The relevant part of my index.js:
async function renderApp() {
const store = await configureStore()
const history = syncHistoryWithStore(browserHistory, store, {
selectLocationState: state => state.get('routing')
})
ReactDOM.render(
<AppContainer>
<MuiThemeProvider muiTheme={muiTheme}>
<Provider store={store}>
<Router history={history} routes={routes(store)} />
</Provider>
</MuiThemeProvider>
</AppContainer>,
document.getElementById('root')
)
}
renderApp()
My store:
// #flow
import 'babel-polyfill'
import { addFormSubmitSagaTo } from 'redux-form-submit-saga/es/immutable'
import { applyMiddleware, createStore, compose } from 'redux'
import { autoRehydrate, persistStore } from 'redux-persist-immutable'
import { browserHistory } from 'react-router'
import { combineReducers } from 'redux-immutable'
import { fromJS } from 'immutable'
import { routerMiddleware } from 'react-router-redux'
import createSagaMiddleware from 'redux-saga'
import rootReducer from './rootReducer'
import sagas from './rootSaga'
export default function configureStore() {
return new Promise((resolve, reject) => {
try {
const sagaMiddleware = createSagaMiddleware()
const middleware = [ routerMiddleware(browserHistory), sagaMiddleware ]
const enhancer = compose(
autoRehydrate(),
applyMiddleware(...middleware)
)
const store = createStore(
combineReducers(rootReducer),
undefined,
enhancer
)
// Decorate with Redux Form Submit Saga
// and create hook for saga's
const rootSaga = addFormSubmitSagaTo(sagas)
sagaMiddleware.run(rootSaga)
// Persist store to the local storage
persistStore(
store,
{ whitelist: ['auth', 'timezone'] },
() => resolve(store)
)
} catch (e) {
reject(e)
}
})
}
Here's my .eslintrc:
{
"env": {
"browser": true,
"jest/globals": true
},
"extends": [
"standard",
"standard-flow",
"plugin:react/recommended"
],
"plugins": [
"compat",
"jest",
"react"
],
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"comma-dangle": ["warn", "only-multiline"],
"compat/compat": 2,
"jest/no-disabled-tests": "warn",
"jest/no-focused-tests": "error",
"jest/no-identical-title": "error",
"max-len": ["warn", 80],
"no-debugger": 0,
"react/jsx-uses-vars": [2]
}
}
Here's my .babelrc:
{
"plugins": [
"react-hot-loader/babel",
"syntax-flow",
"tcomb",
"transform-class-properties"
],
"presets": [
"es2015",
"react",
["env", {
"targets": {
"browsers": ["last 2 versions"]
}
}]
]
}
But whatever I do: I keep getting the following error:
Module build failed: TypeError: Cannot read property 'range' of null
at TokenStore.getTokenBefore (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/token-store/index.js:318:17)
at EventEmitter.checkFunction (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/rules/generator-star-spacing.js:131:42)
at emitOne (events.js:101:20)
at EventEmitter.emit (events.js:191:7)
at NodeEventGenerator.enterNode (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/util/node-event-generator.js:39:22)
at CodePathAnalyzer.enterNode (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:607:23)
at CommentEventGenerator.enterNode (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/util/comment-event-generator.js:98:23)
at Controller.enter (/Users/danielterwiel/dev/nimbus/node_modules/eslint/lib/eslint.js:928:36)
at Controller.__execute (/Users/danielterwiel/dev/nimbus/node_modules/estraverse/estraverse.js:397:31)
at Controller.traverse (/Users/danielterwiel/dev/nimbus/node_modules/estraverse/estraverse.js:501:28)
# multi react-hot-loader/patch webpack-hot-middleware/client babel-polyfill ./src/index.js ./src/style/main.css
I'm not entirely sure what to do. I came accross multiple posts with similar problems, but none of these have lead to an answer until now.
Prior to ESLint supporting ES2017 async/await natively, babel-eslint included workarounds that were removed in babel-eslint#7.0.0. You should either upgrade babel-eslint to v7 or, if you can't do that, use eslint-plugin-babel's patched generator-star-spacing rule.