I'm writing a script that runs an Express server with graphql. I m using ES5.
Here is my server.js code (to run the Express server) :
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const {graphqlExpress, graphiqlExpress} = require('apollo-server-express');
const schemaTest = require('./schemas/schema');
const app = express();
app.listen(4000, () => { console.log("Listening on 4000")});
app.use('/graphql', bodyParser.json(), graphqlExpress({schemaTest}));
app.use('/graphiql', graphiqlExpress({endpointURL: '/graphql'}));
and here is the code of my schema.js
const {makeExecutableSchema, addMockFunctionsToSchema} = require('graphql-tools');
const typeDefs = `type Query {
greeting: String
}
`;
const schema = makeExecutableSchema({typeDefs});
addMockFunctionsToSchema({ schema });
module.exports = schema;
however i'm getting this isse :
Error: Expected undefined to be a GraphQL schema.
and I m not able to find where is my error.
For your informtion, if I copy paste my schema.js code into the server.js file it works correctly, it is like I m not importing (or exporting) the schema file correctly.
Where is my error
graphqlExpress is expecting a configuration object to be passed to it, with one of the properties on that object being schema. So your code should look something like this:
app.use('/graphql', bodyParser.json(), graphqlExpress({
schema: schemaTest,
}));
What you are currently doing is passing in an object with a schemaTest property, but no schema property.
Related
I'm using express-session with sequelize and connect-session-sequelize within my Node.js App. By default express-session logs all SQL calls, which highlighted the issue I am trying to resolve. A call to a view template via res.render('index') initiates both a SELECT and UPDATE call as expected (below):
Executing (default): SELECT `sid`, `expires`, `data` FROM `session` AS `session` WHERE `session`.`sid` = 'T84YX7hvKWmihWPMzT0Cg_97Wao7kCF5';
Executing (default): UPDATE `session` SET `expires`=? WHERE `sid` = ?
However, adding linked header elements (style/script tags) or img tags within the template results in an additional call to both the SELECT and UPDATE query for every linked element. As a result, adding more content will result in an exponential number of database calls.
How can I prevent style,script and img calls from initiating the call within express?
app.js
const config = require('./config');
const http = require('http');
const express = require('express');
const session = require('express-session');
const Sequelize = require('sequelize');
const sequelize = new Sequelize(
config.dbDatabase,
config.dbUser,
config.dbPassword,
{
host : config.dbHost,
dialect : config.dbDialect,
define : {
timestamps : false,
underscored : true
}
}
);
const app = express();
const sequelizeStore = require('connect-session-sequelize')(session.Store);
const sessionStore = new sequelizeStore({
db: database.sequelize,
modelKey: 'session'
});
app.set('view engine', 'pug');
app.set('views', './views');
app.use(express.static('./public'));
app.get('/', function(req, res){
res.render('index'); // pug
}
const server = http.createServer(app);
server.listen(config.port, () => {
console.log(`App listening on port: ${config.port}`);
});
index.pug
doctype html
html
head
meta(charset='utf8')
title example
link(rel='stylesheet' href='/css/example.css')
script(src='/js/lib/angular/angular.min.js')
script(src='/js/lib/angular/angular-resource.min.js')
script(src='/js/example.min.js')
body
H1 Example Template
img(src= "/img/sample.jpg" alt="Sample image")
The issue is caused when app.use(express.static('./public')); is used after app.use(session({...});. Hope this helps anyone else encountering the same issue.
I am working with node, sequelize, migration and mysql. I have already donde the sequelize init and define my models in the file of 'models'. I am testing my first endpoint in the server.js file but when I want run the post it appear the next message :
"Cannot read property 'create' of undefined"
I have read a lot of issues and it is suposed that with the next require y can access my model.
const User = require('./models').User
const express = require('express');
const bodyParser = require('body-parser');
const User = require('./models').User;
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/new', function(req, res){
User.create({
....
}).then((user) => {
....
})}
app.listen(8000)
I am currently using MySQL for the db instead of the popular mongodb, since that is the case there isn't much documentation out there as far as architecture and getting set up. This is my current structure
client
-- angular files
routes
-- index.js
views
-- 404 page
app.js
I don't understand how I can implement controllers or models into this structure. I'm currently grabbing data from the db or sending it with the routes..I'm not sure what the added layer of controllers would do. Maybe this is a dumb question but I would just like to have a clear baseline so that my project will scale well. I feel like there should be way more to this than what I currently have.
index.js
const express = require('express');
const mysql = require('mysql');
const router = express.Router();
const db = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'db'
});
// Connect
db.connect((err) => {
if(err){
throw err;
}
console.log('MySql Connected...');
});
// Select Data
router.get('/getData', (req, res) => {
let sql = 'SELECT * FROM data';
let query = db.query(sql, (err, results) => {
if(err) throw err;
console.log(results);
res.send(results)
});
});
module.exports = router;
app.js
const express = require('express');
const mysql = require('mysql');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const compression = require('compression');
const helmet = require('helmet')
const expressSanitizer = require('express-sanitizer');
const index = require('./routes/index');
const app = express();
const port = 3000;
var corsOptions = {
origin: 'http://localhost:8100',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
// var logger = (req, res, next) => {
// console.log('logging...')
// next();
// }
//added security
app.use(helmet())
// //set logger
// app.use(logger)
//cors options
app.use(cors(corsOptions))
//body parser middleware
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
// Mount express-sanitizer here
app.use(expressSanitizer()); // this line follows bodyParser() instantiations
//set static path
app.use(express.static(path.join(__dirname, 'client')));
// set our default template engine to "ejs"
// which prevents the need for using file extensions
app.set('view engine', 'ejs');
//gzip compression
app.use(compression())
//set views for error and 404 pages
app.set('views', path.join(__dirname, 'views'));
app.use('/', index);
app.use('/fp/trips', trips);
app.listen(port, () => {
console.log('server started on port 3000')
})
When working on Node apps I tend to favor a scheme where controllers are (almost) services -- I think it works really well for small applications.
This is an example:
index.js
let app = express()
let users = require('./services/users')
app.get('/users/:id', async function(req, res, next) => {
try {
res.json(users.getByid(req.params.id))
} catch() {
next(err)
}
})
app.listen(8080)
services/users.js
let db = require('./db')
async function getById(id) {
let conn = await db.connect()
let user = conn.query('SELECT * FROM user WHERE id = ?', [id])
if (!user) {
throw new Error("404")
}
return user
}
module.exports = {getById}
services/db.js
let realDb = require('some-open-source-library-to-interact-with-db')
realDb.initialize(process.env.DB_CREDENTIALS) // pseudo-code here
module.exports = realDb
This though, won't work well when you're building large, complex apps -- I think you will require more structure in that case.
PS: I wouldn't suggest to build a large, complex app ever -- split it into smaller ones where patterns like the one I presented work nicely.
You can use Sequelize as ORM (Object Relational Mapper) for your MySQL DB to make your code more readable and to allow you to create better structure of your app. It also has support for PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL.
There are samples out there how to integrate Sequelize with Express. I'm not sure if I'm allowed to post a github repository here but here it is:
https://github.com/jpotts18/mean-stack-relational
PS. I don't own this repository but this might help you somehow.
I'm trying to get a JSON data which is sent as JSON data using postman tool and trying to receive it my post() method.
var express = require('express');
var app = express();
app.post('/myData',function(req,res){
console.log("--->",req.body);
});
var server = app.listen(8080,function(){});
This is the JSON data sent through postman tool
I'm getting undefined in my console as
"---> undefined"
I'm trying to retrieve the JSON data set in my postman tool to either my console or browser
Corrected. Please try to run this code.
var express = require('express');
var app = express();
app.post('/myData', function (req, res) {
req.on('data', function (data) {
console.log("--->",data.toString());
res.send("Received");
});
});
var server = app.listen(8080, function () { });
Add res.send(req.body); inside the app.post method.
app.post('/myData',function(req,res){
console.log("--->",req.body);
res.send(req.body);
});
Express usually uses a middleware called body-parser to parse the received JSON content. req.body will be empty if you don't enable body-parser or something similar. body-parser is built in for the latest versions of Express. It's enabled like this:
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
So the final code is like this:
var express = require('express');
var app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.post('/myData',function(req,res){
console.log("--->", req.body);
res.send('data received');
});
var server = app.listen(8080,function(){});
I've also added res.send('data received');, because you should send a response when you get a request on a valid endpoint.
I've set up a node server that passes requests to a utility class.
So far the POST request is hit but the mapping to the body property values are undefined. Bodyparser is also used in the post method to assist in the Json parse.
I stepped into the request and see that the body is populated and see that the property names are correct as shown in the paste below:
body: { '{\n\t"Email":"brian#gmail.com",\n\t"Dashboard_Name":"my dash 4",\n\t''},
But the below mapping to the values assinged via req.body.propertyname return undefined:
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
Question:
How can you parse JSON properties from request body in express server?
JSON object posted:
This is the JSON that I post to the server using Postman:
{
"Email":"brian#gmail.com",
"Dashboard_Name":"my dash 4"
}
Gist of the express server and associated utility method SaveUserProfile:
Express server -
var express = require('express');
var UserLDAP = require('./utilities/UserLDAP'); //utility file containing the POST method
var bodyParser = require('body-parser');
const url = require('url');
const app = express();
var sql = require('mssql');
const cors = require('cors');
const path = require('path');
sql.connect("********************************************************************")
.then((connection1) => {
sql.globalConnection = connection1;
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/OOO/SaveUserProfile', UserLDAP.SaveUserProfile)
app.listen(process.env.PORT || 4000 );
logger.info(`listening to port ${process.env.PORT}`);
}).catch((err) => {
res.status(500).send(err.message);
logger.error(err.message);
});
UserLDAP.js -
var sql = require('mssql');
var bodyParser = require('body-parser');
//Save User Profile
exports.SaveUserProfile = function(req, res) {
req.app.use(bodyParser.json());
req.app.use(bodyParser.urlencoded({ extended: true }));
var request = new sql.Request(sql.globalConnection);
console.log(req);
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
};
Turns out I had incorrect content-type set in Postman on the object being posted. Needed to be set as:
application/json; charset=UTF-8
Currently you have no way of knowing if a parser like body-parser.json has produced an error which seems the obvious place to start given the content is there but the result isn't.
I had a look at body-parser and found an issue that spoke to the problem of detecting a json error which I would expect to be good to know.
The developer suggested the following as one method.
app.use(errorFork(bodyParser.json(),
function (err, req, res, next) {
// do stuff with only body parser errors
}))
// this is an example; you can use any pattern you like.
function errorFork(middleware, errorHandler) {
middleware(req, res, function (err) {
if (err) {
return errorHandler(err, req, res, next)
}else{
return next()
}
})
}
It isn't a fix but it would give you more info. Something is going wrong with the parsing by what you have indicated the questin is what? The other thing I noticed about your pasted body content is that it isn't valid json (ignoring \n\t) you have a few rouge ' in there, worth checking. Try copying what is in body (raw) and put it through a json validator site like jsonlint.com just as a double check and see if body-parser is returning any errors.