Implementing Apollo Federation gateway using Express Framework - node.js

I'm currently working on a POC to implement Apollo Federation gateway in and NodeJS + express application. Up until now, I haven't really encountered any example on how to properly do it.
So far, I encounter a problem where the ApolloServer module doesn't recognize an instance of ApolloGateway from #apollo/gateway. I'm using ApolloServer instance as a wrapper of the gateway's instance as shown from the tutorial: https://www.apollographql.com/docs/apollo-server/federation/implementing/#defining-the-gateway. However, I ran into a problem when calling the server.applyMiddleWare() in my express app. I came across the example from https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-express#express
to be specific here is a snippet of the error log:
$ node --use_strict ./bin/www
/Users/evanlee/dev/federation-gateway/node_modules/loglevel-debug/index.js:32
target[k] = attr.bind ? attr.bind(k) : attr;
^
TypeError: Cannot assign to read only property 'name' of function 'function() {
return log.debug.apply(this, arguments);
}'
at /Users/evanlee/dev/federation-gateway/node_modules/loglevel-debug/index.js:32:15
at Array.forEach (<anonymous>)
at composit (/Users/evanlee/dev/federation-gateway/node_modules/loglevel-debug/index.js:30:20)
at Object.loglevelDebug [as default] (/Users/evanlee/dev/federation-gateway/node_modules/loglevel-debug/index.js:201:3)
at new ApolloGateway (/Users/evanlee/dev/federation-gateway/node_modules/#apollo/gateway/dist/index.js:101:33)
at Object.<anonymous> (/Users/evanlee/dev/federation-gateway/app.js:21:12)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
error Command failed with exit code 1.
and here is how I'm trying to integrate the ApolloServer to my express app:
const { ApolloServer } = require('apollo-server');
const { ApolloGateway } = require('#apollo/gateway');
const app = express();
// Apollo Server and Gateway definition
const server = new ApolloServer({
gateway: new ApolloGateway({
debug: true,
serviceList: [
{ name: 'base-app', url: 'http://localhost:4001/graphql' },
]
}),
subscriptions: false,
});
server.applyMiddleware({ app, path: '/graphql' });
really appreciate the help!

It's working for me using latest. However, I'm not using debug: true try without?

Related

Error: Cannot find module 'tslib' on adminbro tutorial

I'm trying to build a nodejs app using admin bro.
They have provided a tutorial for Role Based Access example Here
I run these to create a new directory for the app:
mkdir my-admin-app
cd my-admin-app
yarn init -y
To install dependencies, I ran:
yarn add express express-formidable mongoose admin-bro #admin-bro/mongoose #admin-bro/express
This is the example app...
// Requirements
const mongoose = require('mongoose')
const express = require('express')
const AdminBro = require('admin-bro')
const AdminBroExpressjs = require('#admin-bro/express')
// We have to tell AdminBro that we will manage mongoose resources with it
AdminBro.registerAdapter(require('#admin-bro/mongoose'))
// express server definition
const app = express()
// Resources definitions
const User = mongoose.model('User', {
email: { type: String, required: true },
password: { type: String, required: true },
role: { type: String, enum: ['admin', 'restricted'], required: true },
})
// Pass all configuration settings to AdminBro
const adminBro = new AdminBro({
resources: [User],
rootPath: '/admin',
})
// Build and use a router which will handle all AdminBro routes
const router = AdminBroExpressjs.buildRouter(adminBro)
app.use(adminBro.options.rootPath, router)
// Running the server
const run = async () => {
await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true })
await app.listen(8080, () => console.log(`Example app listening on port 8080!`))
}
run()
To test everything is working as expected...
node index.js
Expected output is this:
AdminBro: bundle ready
Example app listening on port 8080!
But I get this:
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module 'tslib'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
I came across this question but the imports suggested there are not used in the example app so I think the adminbro library already should include those.
Testing environments where this failed:
Local Nodejs version 10 with yarn and npm
A new Nodejs version 15 on docker (brand new container)
Thanks
npm install tslib solved the issue in my casae
This error could happen if you have a js file that requires a tslib but you do not have it installed in the location.
For instance, I had issue with ngx-unused-css which I installed it globally and I do not have tslinb on global.
To fix that, run npm install -g tslib

Couldn't resolve the error coming for mongodb atlas after deploying it on heroku?

In locally the application works perfectly but when i deployed it on heroku it showing errors on heroku logs. Also data wasn't added in mongoDb database. Actually in the application i used google-oauth login so in locally it works perfectly but not in heroku. I've also whitelisted my ip on mongodb atlas but still can't figure out why this error getting.
Anybody help me plz.....
Here is my prod.js file
module.exports = {
googleClientID: process.env.GOOGLE_CLIENT_ID,
googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,
mongoURI: process.env.MONGO_URI,
cookieKey: process.env.COOKIE_KEY
}
Here is my keys.js file
// Keys.js - figure out what credentials should return
if (process.env.NODE_ENV === "production") {
// So we are in prodution - return the prod set of keys
module.exports = require('./prod');
} else {
// We are developement - return the dev keys
module.exports = require('./dev');
}
Here is my index.js file
const express = require('express');
const mongoose = require('mongoose');
const passport = require('passport');
const cookieSession = require('cookie-session');
const keys = require('./config/keys');
require('./models/User');
require('./services/passport');
const app = express();
//Middleware
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
// mongoDb Connection
mongoose.connect(keys.mongoURI, {
useNewUrlParser: true
}).then(() => console.log('MongoDb Connect successfully'))
.catch(err => console.log(err));
// actual routes
require('./routes/authRoutes')(app);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server is running in ${PORT}`));
Actually i getting two different errors first was this
2019-09-02T06:28:59.760121+00:00 app[web.1]: Warning: connect.session() MemoryStore is not
2019-09-02T06:28:59.760149+00:00 app[web.1]: designed for a production environment, as it will leak
2019-09-02T06:28:59.760151+00:00 app[web.1]: memory, and will not scale past a single process.
2019-09-02T06:28:59.763577+00:00 app[web.1]:
2019-09-02T06:28:59.763581+00:00 app[web.1]: /app/node_modules/mongoose/lib/connection.js:519
2019-09-02T06:28:59.763583+00:00 app[web.1]: throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
2019-09-02T06:28:59.763585+00:00 app[web.1]: ^
2019-09-02T06:28:59.763838+00:00 app[web.1]: MongooseError: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.
2019-09-02T06:28:59.763842+00:00 app[web.1]: at new MongooseError (/app/node_modules/mongoose/lib/error/mongooseError.js:10:11)
2019-09-02T06:28:59.763844+00:00 app[web.1]: at NativeConnection.Connection.openUri (/app/node_modules/mongoose/lib/connection.js:519:11)
2019-09-02T06:28:59.763846+00:00 app[web.1]: at Mongoose.connect (/app/node_modules/mongoose/lib/index.js:321:15)
2019-09-02T06:28:59.763848+00:00 app[web.1]: at Object.<anonymous> (/app/index.js:24:10)
2019-09-02T06:28:59.763850+00:00 app[web.1]: at Module._compile (internal/modules/cjs/loader.js:701:30)
2019-09-02T06:28:59.763852+00:00 app[web.1]: at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
2019-09-02T06:28:59.763854+00:00 app[web.1]: at Module.load (internal/modules/cjs/loader.js:600:32)
And the second one is this
2019-09-02T08:49:22.115492+00:00 app[web.1]: { MongoNetworkError: failed to connect to server [productionproj-shard-00-00-qfouv.mongodb.net:27017] on first connect [MongoNetworkError: connection 5 to productionproj-shard-00-00-qfouv.mongodb.net:27017 closed]
So on...... as same as above
Here is my mongodb production url i've been added on heroku config vars
mongodb+srv://nansProdDeploy:nansProdDeploy#productionproj-qfouv.mongodb.net/test?retryWrites=true&w=majority
It's all about whitelisting the correct ip address. When we put our application on heroku we must whitelist the ip by clicking [ Allow Access From Anywhere ] button and then click ok your ip will be 0.0.0.0/0 this ip will allow to access your deployed heroku application. When you are using your application locally at that point of you have to choose [ Add Current Ip Address ] to access your application locally

why cloud funtion in node js doesnt deploy propely

here iam using a cloud functions to create users i am using a express module when i try to deploy this code it deploying to cloud funtions with message that Error : Funtions did not deploy properly
const express = require('express');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const serviceaccount = require('./ServiceAccountKey.json');
const app = express();
admin.initializeApp({
credential: admin.credential.cert(serviceaccount)
});
app.post('/',(req,res)=>{
if(req.method!== 'POST'){
res.status(400).send("what are u trying baby");
return;
}
admin.auth().createUser({
email:req.body.email,
password: req.body.pass,
}).then(function(userRecord){
res.send({'uid': userRecord.uid});
return;
}).catch(function(error){
res.send({'error': 'Try COrrect one baby'});
return;
});
return;
});
exports.register = funtions.Https.onRequest(app);
when i add this at end
module.exports = {
app
}
it showing funtion deployed but its not showing in cloud functions dashboard
what wrong am i doing here
here is the error what ima getting i cnat get whAT THE error is
⚠ functions[register(us-central1)]: Deployment error.
Function failed on loading user code. Error message: Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'express'
at Function.Module._resolveFilename (module.js:476:15)
at Function.Module._load (module.js:424:25)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/user_code/index.js:1:79)
at Module._compile (module.js:577:32)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
Functions deploy had errors with the following functions:
register
You code never uses the firebase-functions modules to declare a Cloud Function. Your functions variable is going unused. You can't just export any function an expect it to run - it has to be built by the SDK.
If you have an express app to deploy, you need to export it via an HTTP type function:
exports.app = functions.https.onRequest(app);
First, I think you need to change the endpoint of the url. Don't just put '/'. Maybe like '/user/create'.
app.post('/user/create',(req,res)=>{
if(req.method!== 'POST'){
res.status(400).send("what are u trying baby");
return;
}
admin.auth().createUser({
email:req.body.email,
password: req.body.pass,
}).then(function(userRecord){
res.send({'uid': userRecord.uid});
return;
}).catch(function(error){
res.send({'error': 'Try COrrect one baby'});
return;
});
return;
});
exports.register = funtions.Https.onRequest(app);
And in your firebase.json you should rewrite the url :
{
"functions": {
...
},
"hosting": {
"public": "public",
"rewrites": [
{
"source": "/user/create",
"function": "register"
}
]
}
}
For more explanation, you can follow this tutorial.

Node application runs on Heroku but not localhost

I have a simple REST API using MEAN. It's hosted on Heroku, and everything works well there. However, if I try to run it on localhost I get the following error:
TypeError: Parameter "url" must be a string, not undefined
at Url.parse (url.js:81:11)
at Object.urlParse [as parse] (url.js:75:5)
at module.exports (/Users/ricardotaboada/Desktop/sbackend/node_modules/mongodb/lib/url_parser.js:15:23)
at connect (/Users/ricardotaboada/Desktop/sbackend/node_modules/mongodb/lib/mongo_client.js:403:16)
at Function.MongoClient.connect (/Users/ricardotaboada/Desktop/sbackend/node_modules/mongodb/lib/mongo_client.js:227:3)
at Object.<anonymous> (/Users/ricardotaboada/Desktop/sbackend/server.js:15:21)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
Any idea what's going on? Thanks very much.
EDIT: Here is the code that connects to Mongo:
mongodb.MongoClient.connect(process.env.MONGODB_URI, function (err, database) {
if (err) {
console.log(err);
process.exit(1);
}
sbrdcontroller = new controller(database);
console.log("Database connection ready");
// Initialize the app.
var server = app.listen(process.env.PORT || 3000, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
});
Hard to say without seeing some code.
That said, from the error message it sounds like you're not passing a valid URL to connect to your mongodb.
EDIT:
Right, so based on your code, check the value of process.env.MONGODB_URI. You can do that from your heroku account or cli, or by console.log, but I'm betting it's not set on your heroku app. Depending on the Mongo addin you use, they use different environment variable names.
process.env.MONGODB_URI is undefined in your local environment which is why the error is being thrown.
Add this code before the database connection code:
var development = process.env.NODE_ENV !== 'production';
var mongo_url;
if (development) {
mongo_url = 'mongodb://localhost:27017/mydb';
}
else {
mongo_url = process.env.MONGODB_URI;
}
Then change:
mongodb.MongoClient.connect(process.env.MONGODB_URI, function (err, database) {
To:
mongodb.MongoClient.connect(mongo_url, function (err, database) {
Assuming your local Mongo database port was not changed, the local URL with port 27017 should work fine.
Now your code should work fine in both development and production.
Maybe dotenv module will be useful for you:
https://www.npmjs.com/package/dotenv

webpack exception when using express middleware router

I have a simple webpack with react hotloader & express setup and working. I'm trying to add an external node module that will register a sub router for some services. For some reason, doing so causes a strange exception (see below).
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var config = require('./webpack.config');
var app = express();
var router = express.Router();
var mod = require("my-module");
mod.registerServices(router); // <-- adds routes to the router
app.use("/api/v1*", router); // <-- This line causes the error
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath,
stats: {
colors: true
}
}));
app.use(require('webpack-hot-middleware')(compiler));
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(3000, 'localhost', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://localhost:3000');
});
The Exception:
$ node server.js
/Users/bmonro/Documents/Code/nui-redux/node_modules/react-transform-hmr/lib/index.js:51
throw new Error('locals[0] does not appear to be a `module` object with Hot Module ' + 'replacement API enabled. You should disable react-transform-hmr in ' + 'production by using `env` section in Babel configuration. See the ' + 'example in README: https://github.com/gaearon/react-transform-hmr');
^
Error: locals[0] does not appear to be a `module` object with Hot Module replacement API enabled. You should disable react-transform-hmr in production by using `env` section in Babel configuration. See the example in README: https://github.com/gaearon/react-transform-hmr
at Object.proxyReactComponents [as default] (/Users/bmonro/Documents/Code/nui-redux/node_modules/react-transform-hmr/lib/index.js:51:11)
at Object.<anonymous> (/Users/bmonro/Documents/Code/nui-redux/src/ext/nui-company-admin/lib/CompanyLocation/components/simple.js:25:60)
at Module._compile (module.js:434:26)
at Object.Module._extensions..js (module.js:452:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object.<anonymous> (/Users/bmonro/Documents/Code/nui-redux/src/ext/nui-company-admin/lib/CompanyLocation/containers/CompanyLocationPage.js:13:25)
at Module._compile (module.js:434:26)
UPDATE
Turns out that removing this from .babelrc where I have some react transforms enabled and subsequently removing all of the web pack hotloader plugins & middleware gets the router working again.
{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}
Try this solution: don't use babel-plugin-react-transform in .babelrc, use config in webpack.config.js
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
include: path.join(__dirname, 'src'),
query: {
plugins: [
["react-transform", {
transforms: [{
transform: "react-transform-hmr",
imports: ["react"],
locals: ["module"]
}]
}]
]
}
}
]
}
Details:
https://github.com/gaearon/babel-plugin-react-transform/issues/62
https://github.com/gaearon/react-transform-hmr/issues/5

Resources