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
Related
I have completed a project and trying to deploy on heroku. I am using Reactjs frontend and express Nodejs with mongoose and mongodb in the Backend. It works on localhost but when I run Build it and try to deploy it on heroku it gives an application error.
Here is my backend connection code:
require('dotenv').config();
const express = require('express')
const session = require("express-session")
const bodyParser = require('body-parser')
const cors = require('cors')
const zomatoRoutes = require('./Routes/zomato')
const paymentRoutes = require('./Routes/payments')
const mongoose = require('mongoose')
const passport = require("passport")
const MongoStore = require('connect-mongo');
const uri = process.env.MONGO_URI || 'mongodb://localhost/zomato';
console.log(uri,'this is the mongo Atlas uri if connected using that !!!')
const options = {
useNewUrlParser: true,
useUnifiedTopology: true,
dbName:'zomato1'
}
const connectDB = async () => {
await mongoose.connect(uri, options ).then(() => {
console.log('mongo connected')
}).catch( e => console.log(e))
}
connectDB().then(() => {
app.listen( process.env.PORT ||5252 , () => {
console.log("express app is up and running on port 5252");
})
})
I also have mongo session store the mongoose session when user logs in
app.use(session({
secret: "this is unambigous secret",
resave: false,
saveUninitialized: false,
cookie: { maxAge: 24*60*60*1000 },
store : MongoStore.create({
client: mongoose.connection.getClient(),
dbName:'zomato1',
ttl: 14 * 24 * 60 * 60
})
}));
app.use(passport.initialize());
app.use(passport.session());
It gives me MongoNotConnectedError: MongoClient must be connected to perform this operation error when I try to deploy using
git push heroku master:main
full error tail :
mongodb+srv://vishal_torne_22:********#db-first-hernode.zu6btrs.mongodb.net/<DBNamecomeshere>?retryWrites=true&w=majority this is the mongo Atlas uri if connected using that !!!
2022-07-31T11:19:34.581869+00:00 app[web.1]: /app/node_modules/mongodb/lib/utils.js:367
2022-07-31T11:19:34.581876+00:00 app[web.1]: throw new error_1.MongoNotConnectedError('MongoClient must be connected to perform this operation');
2022-07-31T11:19:34.581877+00:00 app[web.1]: ^
2022-07-31T11:19:34.581877+00:00 app[web.1]:
2022-07-31T11:19:34.581878+00:00 app[web.1]: MongoNotConnectedError: MongoClient must be connected to perform this operation
2022-07-31T11:19:34.581878+00:00 app[web.1]: at getTopology (/app/node_modules/mongodb/lib/utils.js:367:11)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at Collection.createIndex (/app/node_modules/mongodb/lib/collection.js:258:82)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at MongoStore.setAutoRemove (/app/node_modules/connect-mongo/build/main/lib/MongoStore.js:147:35)
2022-07-31T11:19:34.581881+00:00 app[web.1]: at /app/node_modules/connect-mongo/build/main/lib/MongoStore.js:128:24
2022-07-31T11:19:34.581882+00:00 app[web.1]: at processTicksAndRejections (node:internal/process/task_queues:96:5)
2022-07-31T11:19:34.581882+00:00 app[web.1]:
2022-07-31T11:19:34.581882+00:00 app[web.1]: Node.js v17.9.1
2022-07-31T11:19:34.703486+00:00 heroku[web.1]: Process exited with status 1
2022-07-31T11:19:34.791551+00:00 heroku[web.1]: State changed from starting to crashed
I am using Mongoose to connect the Mongodb, It works on localhost without heroku but when I deploy it using heroku, It asks me to use MongoClient. Is it a requirement to use mongoClient on Heroku 20 stack, I also get warning to upgrade to new Heroku version, I tried to upgrade heroku using npm upgrade heroku to the specifed version it shows successful but again rolls back to heroku 20 stack.
here's what I tried but researching the previous answers :
I added on my mongodb atlas the whitelist 0.0.0.0/0 (includes you current IP address)
I tried to make the mongoose code async so that it connect firsts the database then app listens to the port.
changed the engine version so that it supports latest node and npm version on Heroku like:
{
"version": "1.0.0",
"engines": {
"node": "17.x",
"npm":"8.x"
}
}
Is it a requirement to use MongoClient on heroku 20 stack ? as the Error shows... and why it is showing error on Mongoose.connect()
Thanks in advance..!
As you say it runs fine in your local environment, the issue may be fixed by adding process.env.MONGO_URL to the config vars of your application, as the issue may originate when Heroku tries to connect to your MongoDB, but does not achieve this connection due to an invalid url that is stored in an env variable on your local device.
In my NodeJS app, I have .env file in root directory with following info:
NODE_ENV = development
PORT = 3002
#db credentials
dbURL = 'mongodb+srv://username:password#clusterName-0gcm3.mongodb.net/dbName?retryWrites=true&w=majority'
And in the root directory I also have config file (config.js) which grabs the variables:
const dotenv = require('dotenv');
dotenv.config();
module.exports = {
port: process.env.PORT,
dbURL: process.env.dbURL
}
In my App.js which is again in root folder I am able to successfully read this file and able to connect with DB:
const express = require('express');
const mongoose = require('mongoose');
const { port, dbURL } = require('./config'); //reading the config file and grabbing the vars
const app = express();
app.use(express.json());
//works well!
mongoose.connect(dbURL, { useUnifiedTopology: true, useNewUrlParser: true})
.then(res => {
console.log(`Listening on port ${port}`);
app.listen(port);
})
.catch(err => console.error(err));
Now I am trying to write some standalone scripts to populate the DB with some sample data and in that script I am trying to connect to DB seperately as those scripts will only be executed with node <file> command. This file (dbPopulate.js) is located within /helper-scripts/ folder. And the script looks like this:
const express = require('express');
const mongoose = require('mongoose');
const {port, dbURL} = require('../config'); //attempting to read config.js that calls the .env file
const app = express();
app.use(express.json());
console.log(dbURL, port) //throws undefined for both vars
mongoose.connect(dbURL, { useUnifiedTopology: true, useNewUrlParser: true})
.then(res => {
console.log(`Listening on port ${port}`);
app.listen(port);
})
.catch(err => console.error(err));
Just to make it clear this is my file structure:
/.env
/app.js
/config.js
/helper-scripts/dbPopulate.js (culprit)
UPDATE for displaying error log:
When I execute dbPopulate.js standalone I get following errors:
$ node dbPopulate.js
undefined undefined
C:\teamSIO\server\node_modules\mongoose\lib\connection.js:582
throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
^
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.
at NativeConnection.Connection.openUri (C:\teamSIO\server\node_modules\mongoose\lib\connection.js:582:11)
at Mongoose.connect (C:\teamSIO\server\node_modules\mongoose\lib\index.js:335:15)
at Object.<anonymous> (C:\teamSIO\server\helper-scripts\dbPopulate.js:30:10)
at Module._compile (internal/modules/cjs/loader.js:1123:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1143:10)
at Module.load (internal/modules/cjs/loader.js:972:32)
at Function.Module._load (internal/modules/cjs/loader.js:872:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
I would try using an array instead of an object.
require('dotenv').config();
const port = process.env.PORT;
dbURL: process.env.dbURL;
module.exports = [
port,
dbURL
];
and to use
const [port, dbURL] = require('./config');
Also, I don't think that this was the error, but you do have two dots in your "dbPopulate.js" const {port, dbURL} = require('../config'); file, this might be your problem
It's been a long time since you asked, but maybe my answer will help someone else.
When you execute node dbPopulate.js from directory helper-scripts the function require will be able to correctly load ../config, but that in turn will fail to find the file .env because it expects to find it at the same level, from a file/directory hierarchy perspective.
You can either copy .env inside helper-scripts, which you'd better not, or execute dbPopulate.js from project's root directory.
when u run a node app where the .env file is not in the same relative location as the file u are running then u need to specify the correct path for the .env file.
Example if i have app.js and .env file both inside the same project folder location then when I'll do node app.js, then just dotenv.config() will work fine as its default path is
process.cwd() + '.env'
but for say i have a file inside seeder/chat-message-type.seeder.js then to read the .env file which is outside i have to go out one directory.
const path = require("path")
// have to modify dotenv file path becuase the app is run from seeder folder
dotenv.config({ path: path.join(process.cwd(), "..", ".env") })
This will ensure that whenever i am reading the .env file by running
cd seeder
node chat-message-type.seeder.js
it will still load all the data from .env file.
Am trying to make a simple nodesjs app that shows the entirety of a collection from an existing mongodb database using docker, I have created the nodejs app and dockerized it, I also created a network that includes the containers of both the nodesjs app and the existing mongodb data base. the connection was established successfully but for some reason I don't get any results back.
you will find bellow the code I used to build my simple app :
The database am trying to connect to is called crawlab_test and the collection am trying to show on the nodejs app is called resultnews.
( When i access http://localhost:5001/ i get a result saying Cannot GET /
but when i try to access http://localhost:5001/resultnews to show the collection using my nodejs app i get nothing. )
my server.js file :
const Resultnews = require("./src/Resultnews.model");
const express = require("express");
const app = express();
const connectDb = require("./src/connection");
const PORT = 5001;
app.get("/resultnews", async (req, res) => {
const resultnews = await resultnews.find();
res.json(resultnews);
});
app.listen(PORT, function () {
console.log(`Listening on ${PORT}`);
connectDb().then(() => {
console.log("MongoDb connected");
});
});
i created a folder called src inside it i created two files :
my Resultnews.model.js :
const mongoose = require("mongoose");
const resultnewsSchema = new mongoose.Schema({
title: String,
url: String,
clicks: String,
task_id: String,
});
const Resultnews = mongoose.model("Resultnews", resultnewsSchema);
module.exports = Resultnews;
And my connection.js file :
// connection.js
const mongoose = require("mongoose");
const User = require("./Resultnews.model");
const connection = "mongodb://localhost:27017/crawlab_test";
const connectDb = () => {
return mongoose.connect(connection, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
};
module.exports = connectDb;
Here the Dockerfile i used :
FROM node:12
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
COPY package*.json ./
RUN npm install
# Copy app source code
COPY . .
#Expose port and start application
EXPOSE 5001
CMD [ "npm", "start" ]
the docker commands i used are on this project are :
docker network create enews
to create the network,
docker network connect crawlab_mongo_1
to add the existing mongodb container to my network ,
docker build -f Dockerfile -t mydockerapp .
to build a container from my nodejs app and finally
docker run -d --net=enews --name mydockerapp -p 5001:5001 mydockerapp
to run the container and add to my network.
ps : the app works fine when using a local mongodb database so am guessing the problem is from my docker run commands but i cant seem to find it.
thank you in advance for everyone who might help me with this problem.
Because it's const Resultnews = require("./src/Resultnews.model");
But the result in app.get() is resultnews.
One is starts with cap and one starts with lower case.
UPDATE:
When running on Docker for Win or Docker for Mac, you can use the
hostname host.docker.internal inside your container to access
resources on your host: host.docker.internal:27017
On Linux there seems to be no such feature. However, some workarounds
exist, which you can find in this issue:
https://github.com/docker/for-linux/issues/264
Check out this post: https://www.reddit.com/r/docker/comments/a0ge2d/accessing_mongodb_from_docker_container/
I am trying to deploy a NodeJS live streaming server which works on heroku built on rtmp server using node-media-server and socket.io. I am facing issue in starting the node-media-server since it needs 2 ports to run as per config format:
const NodeMediaServer = require('node-media-server');
const config = {
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 30,
ping_timeout: 60
},
http: {
port: 8000,
allow_origin: '*'
}
};
var nms = new NodeMediaServer(config)
nms.run();
I've tried deploying app on new heroku app by following official guide. Since Heroku provides only one port per dyno, it gives me these logs on my heroku app dashboard:
2020-04-07T23:08:24.289041+00:00 app[web.1]: 4/7/2020 23:08:24 23 [ERROR] Node Media Trans Server startup failed. ffmpeg:/usr/local/bin/ffmpeg cannot be executed.
2020-04-07T23:08:24.290753+00:00 app[web.1]: (node:23) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
2020-04-07T23:08:24.291397+00:00 app[web.1]: listening on port 19586
2020-04-07T23:08:24.292059+00:00 app[web.1]: 4/7/2020 23:08:24 23 [ERROR] Node Media Rtmp Server Error: listen EADDRINUSE: address already in use :::19586
2020-04-07T23:08:24.292694+00:00 app[web.1]: 4/7/2020 23:08:24 23 [ERROR] Node Media Http Server Error: listen EADDRINUSE: address already in use :::19586
2020-04-07T23:08:24.293383+00:00 app[web.1]: 4/7/2020 23:08:24 23 [ERROR] Node Media WebSocket Server Error: listen EADDRINUSE: address already in use :::19586
2020-04-07T23:08:24.682440+00:00 heroku[web.1]: State changed from starting to up
2020-04-07T23:08:24.693405+00:00 app[web.1]: Connected to the database
I need to know how I can deploy my app on heroku (or any other alternative) to make it available in production mode. My server works fine on my MacBook Pro.
Here's my code:
const { NodeMediaServer } = require('node-media-server');
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const http = require('http');
const fs = require('fs');
const bodyParser = require('body-parser');
const path = require('path');
const process = require('process')
const port = process.env.PORT||5000
const port2 = process.env.PORT||8000
const port3 = process.env.PORT||8001
const server = http.createServer(app);
const io = require('socket.io').listen(server);
require('./app/controllers/socketIO')(io);
mongoose.Promise = global.Promise;
global.appRoot = path.resolve(__dirname);
mongoose.connect(
"mongodb://databasecredentials",
{ useNewUrlParser: true },
err => {
if (err) {
console.log(err);
} else {
console.log('Connected to the database');
}
}
);
app.use(
bodyParser.urlencoded({
extended: true
})
);
app.use(bodyParser.json());
app.set('socketio', io);
app.set('server', server);
app.use(express.static(`${__dirname}/public`));
server.listen(port, err => {
if (err) {
console.log(err);
} else {
console.log(`listening on port ${port}`);
}
});
const nodeMediaServerConfig = {
rtmp: {
port: port2,
chunk_size: 60000,
gop_cache: true,
ping: 60,
ping_timeout: 30
},
http: {
port: port3,
mediaroot: './media',
allow_origin: '*'
},
trans: {
ffmpeg: '/usr/local/bin/ffmpeg',
tasks: [
{
app: 'live',
ac: 'aac',
mp4: true,
mp4Flags: '[movflags=faststart]'
}
]
}
};
var nms = new NodeMediaServer(nodeMediaServerConfig);
nms.run();
I'm not very familiar with Heroku, but in the first line of the logs it states:
[ERROR] Node Media Trans Server startup failed. ffmpeg:/usr/local/bin/ffmpeg cannot be executed.
you need to install ffmpeg on the machine running the code. This is the first step to get your server starting (this might not fix all the problems you're having but this is the first thing you need to start with).
I'm trying to do something similar using GCP. In order to get it to run, I created a package.json file and set the start script to apt install --fix-missing --assume-yes ffmpeg && node app.js as a temporary workaround:
{
"name": "app-service-hello-world",
"description": "Simple Hello World Node.js sample for Azure App Service",
"version": "0.0.1",
"private": true,
"license": "MIT",
"author": "Microsoft",
"scripts": {
"start": "apt install --fix-missing --assume-yes ffmpeg && node app.js"
},
"dependencies": {
"node-media-server": "^2.1.9"
}
}
This might help you adding ffmpeg correctly to your Heroku environment: Install FFMPEG on Heroku
I'm following the tutorial here: Implementing GraphQL Using Apollo On an Express Server and I'm getting the error GET query missing in the browser at http://localhost:7700/graphql.
First I typed all the code myself. When I encountered the error, I downloaded the code from GitHub: kimobrian/GraphQL-Express: An Express Server implemented using GraphQL to eliminate the possibility that I had made a mistake. However, I'm still getting the same error.
I presume it is better to provide the link to the repo rather than paste the code here because I'm using the same code from the repo. Also, I am not sure which file might contain the problem.
$ npm start
> tutorial-server#1.0.0 start kimobrian/GraphQL-Express.git
> nodemon ./server.js --exec babel-node -e js
[nodemon] 1.18.9
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node ./server.js`
GraphQL Server is now running on http://localhost:7700
The error is GET query missing in the browser at http://localhost:7700/graphql. It's the same in Firefox and Chromium.
Update: The only question I find with relevant information is here: nodejs with Graphql. The suggested solution is
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
However, that's exactly the code I have already (from the tutorial). Here is my entire server.js:
import express from 'express';
import cors from 'cors';
import {
graphqlExpress,
graphiqlExpress,
} from 'graphql-server-express';
import bodyParser from 'body-parser';
import { schema } from './src/schema';
const PORT = 7700;
const server = express();
server.use('*', cors({ origin: 'http://localhost:7800' }));
server.use('/graphql', bodyParser.json(), graphqlExpress({
schema
}));
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql'
}));
server.listen(PORT, () =>
console.log(`GraphQL Server is now running on http://localhost:${PORT}`)
);
Both the API and the package name itself have changed since that tutorial was written (the package is now apollo-server-express). You no longer need to import cors or body-parser. The simplest way to get started is to actually just use apollo-server:
const server = new ApolloServer({ typeDefs, resolvers });
const port = 7700;
server.listen({ port });
If you still want to apply other middleware yourself, you can use apollo-server-express:
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
const port = 7700;
app.listen({ port });
Please check the official docs for more details.
I fixed it by addding two fields into Apollo Server constructor: playground: true and introspection: true:
const apolloServer = new ApolloServer({
schema,
context: (ctx: Context) => ctx,
playground: true,
introspection: true,
});
Note: Beware that cors should be set up properly for your graphql server to be able to answer requests.
Found here.