nodejs with Graphql - javascript

I am facing an issue, while trying graphQL. I guess I am doing something wrong at schema or resolver. Everything according to docs but still not able to get the data.
What Do I need is very simple user model to run its queries in graphiql.
Here is my code: Download code (zip file) (code for node-7.5)
and then just run npm install and npm run build.
Main files: server.js, schema.js, models/user.js and resolvers/user.js.
models/user.js
const typeDefinitions = `
type User {
id: String!
name: String
type: Int
isActive: Boolean
clients: [String]
}
schema {
query: User
}
`;
export default [typeDefinitions]
resolvers/user.js:-
const resolverMap = {
User: {},
};
export default resolverMap
schema.js
import { makeExecutableSchema } from 'graphql-tools';
import resolver from '../resolvers/user'
import User from './user';
export default makeExecutableSchema({
typeDefs: User,
resolvers: resolver,
});
server.js:-
import express from 'express';
import bodyParser from 'body-parser';
import routes from './app/routers/index';
import { graphqlExpress } from 'graphql-server-express';
import schema from './app/models/schema'
var app = express(); // create our app w/ express
var database = require('./app/configs/database');
var port = process.env.PORT || 8888; // set the port
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({ 'extended': 'true' })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use('/graphql', bodyParser.json(), graphqlExpress({
graphiql: true,
pretty: true,
schema: schema
}));
app.listen(port);
console.log("App listening on port : " + port);

import { graphiqlExpress } from 'graphql-server-express';
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
You need to use above code,
graphiql: true is not supported anymore I guess,
You need to import a graphiql method and pass an endpoint for the same

Related

How to pass pusher to utility classes in node.js

I am using Node.js here with Pusher,
but it's not a pusher related question, it's more of a Node.js question.
In Server.js (declare pusher, and used pusher once for authentication)
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser'
import Pusher from 'pusher'
const PORT = 4001;
const app = express();
app.use(cors());
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
const pusher = new Pusher({
appId: "ddsd",
key: "afdafa",
secret: "asdfasdfasfadsf",
cluster: "mt1",
useTLS: true
});
app.post("/pusher/user-auth", (req, res) => { //<--pusher is used once here for authentication
const socketId = req.body.socket_id;
const user = {id: '12345'};
const authResponse = pusher.authenticateUser(socketId, user);
res.send(authResponse);
});
I have a utility file call controllers/messagesWebsocketController
class messagesWebsocketController()
async sendMessageToClients (message) {
pusher.sendToUser("12345", "my-event1", { message}); //<--how do I pass pusher in?
}
const messagesWebsocketController = new MessagesWebsocketController();
export default messagesWebsocketController;
So other classes can simply
import messagesWebsocketController from 'controllers/messagesWebsocketController'
...
messagesWebsocketController.sendMessageToClients("hello");
The question is for controllers/messagesWebsocketController, how do I pass the pusher instance in from server.js?
You can create separate file for pusher, export it and you can use it wherever you like in your app.
const pusher = new Pusher({
appId: 'ddsd',
key: 'afdafa',
secret: 'asdfasdfasfadsf',
cluster: 'mt1',
useTLS: true
});
export default pusher;
then use it like this
import pusher from 'pusher.js'

mongoose.connection.once('open') callback never firing

I'm currently setting up a custom Node server with Next.js. The fact that I'm using Next.js shouldn't make any difference though.
In previous apps, I've always used mongoose.connection.once('open', callback) to start listening only when the database is open. This time, it's not working.
This is my connection configuration file:
import mongoose from 'mongoose';
import { MONGO_URI } from '../constants'; // looks like 'mongodb://localhost/my-db' in development
mongoose
.connect(MONGO_URI, () => {
try {
console.log(`Connected to ${MONGO_URI} with Mongoose.`);
} catch (err) {
throw err;
}
})
export default mongoose.connection;
I am importing this and using it in my main.ts file like so:
import express from 'express';
import next from 'next';
import * as dotenv from 'dotenv';
import logger from 'morgan';
import compression from 'compression';
import helmet from 'helmet';
import rateLimiter from './config/rateLimiter';
import db from './config/connection'; // This is the config file
dotenv.config();
const PORT = process.env.PORT || '8000';
const dev = process.env.NODE_ENV !== 'production';
const nxt = next({ dev });
const handle = nxt.getRequestHandler();
nxt.prepare().then(() => {
const app = express();
app.enable('trust proxy');
app.use(logger('dev'));
app.use(helmet());
app.use(rateLimiter);
app.use(compression());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
db.once('open', () => {
app.listen(PORT, () => {
// This log never happens
console.log(`Listening on port ${PORT}.`);
});
});
});
It's extremely strange, because "Connected to mongodb://localhost/my-db with Mongoose." is in fact logged when using the code above, but the express app simply never listens; however, when I remove the app.listen out of the db.once callback function, "Listening on port 8000" does of course get logged.
I'm stumped. Why isn't the 'open' event firing? I've verified that mongo is working locally through the Mongo shell, and this same exact code was working when I had the folder which these files are in (server) separate from the Next.js app (when I was still debating which type of view layer to write).
The issue is not compatibility. I'm running Mongo 5.0.5, and Mongoose 6.2.5, which should be find according to this
Please don't link to some other question. None of these have helped:
My mongo is compatible
mongoose.connect doesn't return a promise
The comment from #Shivam Sood was correct. The db.once('open') was being called too late. Once nxt.prepare had happened, the db was already opened.
Here is the modified code:
import express from 'express';
import next from 'next';
import * as dotenv from 'dotenv';
import logger from 'morgan';
import compression from 'compression';
import helmet from 'helmet';
import rateLimiter from './config/rateLimiter';
import db from './config/connection';
dotenv.config();
const PORT = process.env.PORT || '8000';
const dev = process.env.NODE_ENV !== 'production';
const nxt = next({ dev });
const handle = nxt.getRequestHandler();
db.once('open', () => { // Listen for 'open' event before nxt.prepare, and before listening on PORT
nxt.prepare().then(() => {
const app = express();
app.enable('trust proxy');
app.use(logger('dev'));
app.use(helmet());
app.use(rateLimiter);
app.use(compression());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.get('*', (req, res) => {
return handle(req, res);
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}.`);
});
});
});

Node API - Cannot GET /url

I know there are several version of this but I can't seem to find a solution for mine.
My server doesn't seem to see all routes in my routes file. It only matches the first one.
index.js
import express from 'express'
import mongoose from 'mongoose'
import dotenv from "dotenv";
import tweetRoutes from "./src/routes/tweetRoutes.js";
dotenv.config();
const app = express();
const PORT = process.env.PORT || 5000;
app.use(express.json());
// Routes
app.use("/api/tweets", tweetRoutes);
// DB connection
mongoose.connect(process.env.DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.connection.on("connected", () =>
console.log("DB Connection Established!")
);
// Server
app.listen(PORT, () => console.log(`Server listening on: ${PORT}`))
tweetRoutes.js
import { Router } from 'express'
import {
createTweet,
fetchTweets,
fetchTweet,
updateTweet,
deleteTweet,
} from "../controller/tweetController.js";
const router = Router();
router.get("/", fetchTweets);
router.get("/:id", fetchTweet);
router.post("/create-tweet", createTweet);
router.patch("/:id", updateTweet); // Not working
router.delete("/:id", deleteTweet); // Not working
export default router;
In this case, the only route accessible is the first one, fetchTweets. Even when I pass an ID param to get a single tweet using the fetchTweet route, it routes to the first route. The other routes return a 404.
What could I be doing wrong? Any help is highly appreciated.
Thank you for providing the url you used to test the fetchTweet route.
You should use the following path instead to reach the desired route:
127.0.0.1:3000/api/tweets/61b9af93e88ee4de51c28b95
Reference:
https://expressjs.com/en/guide/routing.html

Cannot get sessions in apollo server context?

I ran into that issue:
I cannot get the access the session object in the request object inside the apollo server context, so I get undefined as output.
Otherwise I can access the session object in the request object inside express routes as normal.
How can I solve that?
import express, { Application, Request, Response } from 'express';
import bodyParser from "body-parser";
import helmet from "helmet";
import xss from 'xss';
import moment from "moment";
import passport from "passport";
import { connect } from "mongoose";
import "reflect-metadata";
import { ApolloServer } from 'apollo-server-express';
import { buildSchema, ResolverData } from "type-graphql";
// Import resolvers
import main_config from './main.config';
import AuthenticationRoutes from './Authentication/Authentication.routes';
import './Authentication/Authentication.strategies';
import {
topicResolver, docsResolver, courseResolver, articleResolver, projectIdeaResolver
} from './Graphql/Topics/Topics.resolvers';
import cookieSession from 'cookie-session';
import expressSession from 'express-session';
// const expGql = require("express-graphql");
const app : Application = express();
// Init cookie cookie-session
app.use(cookieSession({
keys : ["IDFVBHNIOVFFBUE"],
name : 'DBDIUN',
secret : "IDFVBHNIOVFFBUE"
}));
async function runapp (){
// Ïnit passport app and routes
app.use(passport.initialize());
app.use(passport.session())
// Run apollo server
const apollo = new ApolloServer({
schema : await buildSchema({
resolvers : [
topicResolver, docsResolver, courseResolver, articleResolver, projectIdeaResolver
],
globalMiddlewares: [],
}),
context: ({ req, res }) =>{
console.log("context")
console.log(req.session.passport) // cannot get session object then Get undefined
return {
getUser: () => req.user,
logout: () => req.logout(),
}
},
playground : true
})
apollo.applyMiddleware({ app });
// Init body parser and helmet
app.use(helmet());
app.use(bodyParser.json());
app.use('/auth', AuthenticationRoutes)
}
runapp();
Don´t deconstruct req work for me:
context: (req, res) => {
return {
req: req,
res: res,
}
};

ExpressJs - route params are not showing in the req.params property

New to nodejs world. Trying to create a REST Service with express and I'm stuck trying to debug this issue... I want to call a GET resource that has a route param in router.use('/applications/:appId/messages', messageRoutes);
index.js
import Promise from 'bluebird';
import mongoose from 'mongoose';
import config from './config/env';
import app from './config/express';
// plugin bluebird promise in mongoose
mongoose.Promise = Promise;
// connect to mongo db
mongoose.connect(config.db, { server: { socketOptions: { keepAlive: 1 } } });
mongoose.connection.on('error', () => {
throw new Error(`unable to connect to database: ${config.db}`);
});
const debug = require('debug')('express-mongoose-es6-rest-api:index');
// listen on port config.port
app.listen(config.port, () => {
debug(`server started on port ${config.port} (${config.env})`);
});
export default app;
/config/express.js
import express from 'express';
import bodyParser from 'body-parser';
import routes from '../server/routes';
const app = express();
// parse body params and attache them to req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
[...]
// mount all routes on /api path
app.use('/api', routes);
[...]
export default app;
/server/routes/index.js
import express from 'express';
import userRoutes from './user';
import messageRoutes from './message';
import applicationRoutes from './application';
import authRoutes from './auth';
const router = express.Router(); // eslint-disable-line new-cap
// mount message routes at /messages
router.use('/applications/:appId/messages', messageRoutes);
export default router;
/server/routes/message.js
import express from 'express';
import validate from 'express-validation';
import paramValidation from '../../config/param-validation';
import messageCtrl from '../controllers/message';
const router = express.Router(); // eslint-disable-line new-cap
router.route('/')
/** GET /api/applications/:appId/messages - Get list of messages */
.get(messageCtrl.getByAppId);
export default router;
/server/controllers/message.js
import mg from 'mongoose'
import Message from '../models/message';
import moment from 'moment';
function getByAppId(req, res, next) {
//return res.json(req.message);
console.log(req);
}
export default {getByAppId};
The result of console.log(req) is a printout of the request object but the params array is blank.
baseUrl: '/api/applications/57fcf8129eb1d52f1cb10332/messages',
originalUrl: '/api/applications/57fcf8129eb1d52f1cb10332/messages/',
_parsedUrl:
Url {
protocol: null,
slashes: null,
[...]
params: {},
query: {},
Can anyone offer any guidance? Much appreciated. Not sure why the params are blank. Could it be the :appId variable declaration in express router.use() statement?

Categories