I can't run the node.js server using keystone.js framework - keystonejs

I have source code using keystone.js, and I can't run it because of a Mongodb connection error.
This is the code creating Keystone.
const keystone = new Keystone({
name: process.env.PROJECT_NAME,
adapter: new Adapter({dbName}),
mongo: 'mongodb://127.0.0.1:27017/',
sessionStore: new MongoStore({ url: 'mongodb://localhost/' }),
cookieSecret: 'process.env.COOKIE_SECRET',
appVersion: {
version: '1.0.0',
addVersionToHttpHeaders: false,
access: false,
},
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
sameSite: false
}
});
...
await keystone.connect()
Here are the error details:
(node:9928) UnhandledPromiseRejectionWarning: Error: No MongoDB connection URI specified.
at resolveAllKeys (E:\Node.JS\frostbets-master-2-20210809T155720Z-001\frostbets-master-2\keystone\node_modules\#keystonejs\utils\dist\utils.cjs.dev.js:51:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async Keystone.connect (E:\Node.JS\frostbets-master-2-20210809T155720Z-001\frostbets-master-2\keystone\node_modules\#keystonejs\keystone\lib\Keystone\index.js:450:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:9928) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:9928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
------------------------------------------------------------------------------------------

You haven't specified but it looks like you're on Keystone 5 so I'm going with that assumption.
There are a number of issue in the code you've posted:
The main problem you have is you're passing dbName to init you Adapter but you should be passing the full mongoUri.
That's the source of the specific error you're getting.
Pretty sure dbName was an option at one point but not in the current release of KS5.
Again, not sure which version you're actually on but if you've updated some packages in an older project, that might be it.
I'm not sure what the mongo key being passed in the Keystone config but I don't think it's valid.
Any config for Mongo (for the main DB) should be passed to the adapter.
The syntax you're using to create your MongoStore instance has been deprecated for the current version of that package.
If it works for you leave it, but in the code below I've used the more recent MongoStore.create() syntax.
In your code you have mongodb://127.0.0.1:27017/ (under the mongo key, which I think is ignored) and mongodb://localhost/ for the sessionStore.
For most systems this will refer to the same DB though it's not clear if that's intentional in your case.
In my code I've put the sessions in a separate DB (my-app-sessions) but that's optional.
Your config uses the literal string 'process.env.COOKIE_SECRET' as the cookie secret, not the value in the COOKIE_SECRET environment var.
This is almost certainly not what you want.
To solve these problems, you probably want something close to this:
const { Keystone } = require('#keystonejs/keystone');
const { GraphQLApp } = require('#keystonejs/app-graphql');
const { AdminUIApp } = require('#keystonejs/app-admin-ui');
const MongoStore = require('connect-mongo');
const { MongooseAdapter: Adapter } = require('#keystonejs/adapter-mongoose');
const keystone = new Keystone({
name: process.env.PROJECT_NAME,
adapter: new Adapter({ mongoUri: 'mongodb://localhost/my-app' }),
sessionStore: MongoStore.create({ mongoUrl: 'mongodb://localhost/my-app-sessions' }),
cookieSecret: process.env.COOKIE_SECRET,
appVersion: {
version: '1.0.0',
addVersionToHttpHeaders: false,
access: false,
},
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
sameSite: false
}
});
// ...
module.exports = {
keystone,
apps: [new GraphQLApp(), new AdminUIApp({ name: process.env.PROJECT_NAME, enableDefaultRoute: true })],
};
In this code I've left the standard exports at the bottom rather than calling keystone.connect() directly so I can run it with yarn keystone dev.
Tested with..
"dependencies": {
"#keystonejs/adapter-mongoose": "^11.2.2",
"#keystonejs/app-admin-ui": "^7.5.2",
"#keystonejs/app-graphql": "^6.3.2",
"#keystonejs/keystone": "^19.3.3",
"connect-mongo": "^4.4.1"
}

Related

Jest + knex 'Unable to acquire a connection' during integration tests (sequelize works fine)

I have both sequelize and knex in my project (node.js, express, using TypeScript). Just introduced knex as I don't like sequelize and just want a light-weight query builder.
In non-test environments both sequelize and knex work fine, however when running tests (using jest) knex is, apparently, not able to connect to the database. They both use the same databaseUrl, though sequelize has a few more options configured. When running my tests under jest I can't figure out why I am getting
Error: Unable to acquire a connection\n at
Client_PG.acquireConnection
When NODE_ENV is set to 'test', the express app uses a postgres database on my local machine.
Here is the configuration code
const _sqlz = new Sequelize(
config.dbConString,
{
logging: config.nodeEnv === 'test' ? false : false,
define: { freezeTableName: true },
dialect: 'postgres',
...config.sslDB === 'true'
? {
dialectOptions: {
ssl: {
require: true,
rejectUnauthorized: false
}
}
}
: {}
}
);
const knexConfig = {
client: 'postgres',
connection: config.dbConString,
pool: {
min: 0,
max: 15
}
};
const _knex = knex(knexConfig)
When running jest it will give me a Unable to acquire a connection when trying to execute a simple knex query like so
await _knex('myTable').select('*');
To figure out what's happening I configured things such that jest would use the same test database when I set my node environment to be development, i.e. NODE_ENV=development. Interestingly now that development and test point to the same local database, if I run jest, it still gives me the same error about not being able to acquire a connection. So me setting NODE_ENV=test in of itself is not the issue. If I run the app (npm run start) while pointing to my local database, knex works fine, which leads me to think something about jest + knex isn't meshing well. jest + sequelize is working fine.
I tried playing around with the SSL settings but to no avail (I did see some knex + heroku blog posts needing ssl to be explicitly set), e.g.:
const knexConfig = {
client: 'pg',
connection: {
connectionString: config.databaseUrl,
ssl: {
require: true,
rejectUnauthorized: false
}
},
pool: {
min: 0,
max: 15
}
};
Hoping someone with more experience might have some ideas.
Thanks

Reference Error with module exports event discord.js

I am very confused by this error. In my code I have /events/ and /commands/ this is in /events/ I made sure that everything else works but this I can't figure out. The code down below is meant to work as a server count for a website. Anybody know? Thank you.
const Discord = require('discord.js');
var db = require('mysql');
var con = db.createConnection({
host: "localhost",
user: "",
password: "",
database: ""
});
module.exports = (client, guildCreate) => {
//welcome embed
const welcomeEmbed = new Discord.MessageEmbed()
.setColor('#858884')
.setTitle('Hello!')
.setAuthor('DHL Bot', 'https://cdn.discordapp.com/app-icons/708717412391845988/967e1b05f7b8aeca1d6b4649dc5530c8.png')
.setDescription(`Hello I am DHL, I am devoloped by Den#0762. Please do !setup. For support you can join our support server https://discord.com/invite`)
.setTimestamp()
.setFooter('By: Den#0762', 'https://cdn.discordapp.com/avatars/407206318911258628/e972b589e0ea4c45064d39b0380d77fd.png')
guild.owner.send(welcomeEmbed)
//db for scount
con.connect(function(err) {
if (err) throw err;
var sql = "UPDATE scount SET servercount = servercount + 1";
con.query(sql, function (err, result) {
console.log(result.affectedRows + " new server");
});
});
}
(node:1949) UnhandledPromiseRejectionWarning: ReferenceError: guild is not defined
at module.exports (/root/dc/DHL/events/guildCreate.js:23:1)
at Client.emit (events.js:315:20)
at Object.module.exports [as GUILD_CREATE] (/root/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js:33:14)
at WebSocketManager.handlePacket (/root/node_modules/discord.js/src/client/websocket/WebSocketManager.js:386:31)
at WebSocketShard.onPacket (/root/node_modules/discord.js/src/client/websocket/WebSocketShard.js:436:22)
at WebSocketShard.onMessage (/root/node_modules/discord.js/src/client/websocket/WebSocketShard.js:293:10)
at WebSocket.onMessage (/root/node_modules/ws/lib/event-target.js:125:16)
at WebSocket.emit (events.js:315:20)
at Receiver.receiverOnMessage (/root/node_modules/ws/lib/websocket.js:797:20)
at Receiver.emit (events.js:315:20)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1949) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1949) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
You're referencing guild, but it isn't declared. Based on other code I've seen, I think you need something along these lines:
module.exports = (client, guildCreate) => {
//welcome embed
const welcomeEmbed = new Discord.MessageEmbed() [...]
client.on("guildCreate", guild => {
guild.owner.send(welcomeEmbed)
});
[...]

Scheduling localhost serverless cron: The model could not be resolved in registry

I'm hosting an ExpressJS/NodeJS API on AWS Lambda with Serverless framework. The API uses Knex.js and Bookshelf.js ORM.
I want to test scheduling a cron job locally. I'm using serverless-offline-scheduler to do this.
Question: My API runs fine if I call it from my client, but if I call a function via serverless scheduler, it complains that no models are in the registry. Why is this? I've already definitely included all necessary Models at the top of the OrderService.js file.
{
"errorMessage": "The model User could not be resolved from the registry plugin.",
"errorType": "Error",
"stackTrace": [
"Error: The model User could not be resolved from the registry plugin.",
" at new ModelNotResolved (/Users/danielturcotte/Sites/d2c/api_v4/node_modules/bookshelf/lib/plugins/registry.js:70:133)",
Serverless.yml:
functions:
app:
handler: handler.handler
events: ...
dequeue:
handler: ./services/OrderService.dequeue // Call dequeue function
events:
- schedule: rate(1 minute)
The handler calls root/services/OrderService.dequeue function, which contains
...
const dequeue = async function() {
await checkQueuedOrders();
};
module.exports = {
dequeue,
};
In my knexService.js file, I register Bookshelf models to the registry to remove circular dependencies:
const knexfile = require('./knexfile');
const config = require('./environment');
const environment = config.env.NODE_ENV || 'development';
const knex = require('knex')(knexfile[environment]);
knex.client.pool.numPendingCreates();
const bookshelf = require('bookshelf')(knex);
bookshelf.plugin('registry'); // Resolve circular dependencies with relations
bookshelf.plugin('visibility');
bookshelf.plugin('pagination');
module.exports.knex = knex;
module.exports.bookshelf = bookshelf;

Frequent timeout with app using Serverless Framework (AWS Lambda/Gateway), Express, Mongoose/MongoDB Atlas

Trigger warning : Beginner question.
I built an api using Express and Mongoose with a MongoDB Atlas DB.
Most of the time, it works normally, but often I get timeout errors. This seems to happen very randomly and concerns all routes, etc... Precisely, I get :
`502 Internal server error via POSTMAN`
and in the Serverless Dashboard, I get :
invocation
time invoked 1 day ago, mar 08 at 1:38pm
fatal error Function execution duration going to exceeded configured timeout limit.
cold start
duration 48.9 s
memory used na
request
endpoint /{proxy+}
method POST
status 502
message Internal server error
latency 27 ms
and span & log :
I used this tutorial to wrap my express app to deploy it with serverless framework : https://dev.to/adnanrahic/a-crash-course-on-serverless-apis-with-express-and-mongodb-193k
Serverless.yml file :
service: serviceName
app: appName
org: orgName
provider:
name: aws
runtime: nodejs12.x
stage: ${env:NODE_ENV}
region: eu-central-1
environment:
NODE_ENV: ${env:NODE_ENV}
DB: ${env:DB}
functions:
app:
handler: server.run
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
plugins:
- serverless-offline # Utiliser pour tester localement
- serverless-dotenv-plugin
server.js file :
const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(app)
app.js file :
const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const newRoutes = require('./routes/file')
const app = express()
app.use(bodyParser.json())
const helmet = require('helmet')
app.use(helmet())
app.options('*', cors())
app.use(cors({ allowedHeaders: 'Content-Type, Authorization' }))
app.use('/new-route', newRoutes)
app.use((error, req, res, next) => {
console.log(error)
const status = error.status || 500
const message = error.message
res.status(status).json({
status: status,
message: message
})
})
// Gère la connexion à la base de donnée :
require('./db')
module.exports = app
and finally db.js file :
const mongoose = require('mongoose')
mongoose
.connect(
process.env.DB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log('connected')
})
.catch(err => console.log(err))
From what I have read, it is related to cold start in Lambda and the way API Gateway handles timeouts (!?). I have read this on mongoose documentation (https://mongoosejs.com/docs/lambda.html), and read also other tutorials, but I don't how exaclty I should adapt it to my situation.
Thank you for your help
Under your provider add timeout, maximum value of timeout in lambda is
900 seconds, place it according to your execution time like 30 seconds
and see what happens
provider:
timeout: 30
The error is clearly saying that it's execution exceeded timeout, since you have not configured timeout so it was using default timeout of 3 seconds, hopefully it will solve the issue
The issue is likely due to your open database connection. While this connection is established any calls to callback won't be returned to the client and your function will timeout.
You need to set context.callbackWaitsForEmptyEventLoop to false.
Here is the explanation from the docs:
callbackWaitsForEmptyEventLoop – Set to false to send the response right away when the callback executes, instead of waiting for the Node.js event loop to be empty. If this is false, any outstanding events continue to run during the next invocation.
With serverless-http you can set this option quite easily within your server.js file:
const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(app, { callbackWaitsForEmptyEventLoop: false })

Express server crashing due to MongoDB connection loss

I am having issues with an HTTP Node.js server built with:
Ubuntu 14.04
MongoDB 3.0.4
iojs v2.3.3
express=4.10.*
mongodb=1.4.34
The following middleware are being used:
app.use(response_time());
app.use(body_parser.urlencoded({extended: true}));
app.use(body_parser.json());
var MongoClient = require('mongodb').MongoClient;
app.use(function (req, res, next) {
var connection_options = {auto_reconnect: false};
MongoClient.connect(config.server.db, connection_options, function (err, db) {
if (err) {
log.error(err); // Logging error.
return next(err);
}
req.db = db;
next();
});
});
The server started running at 20:40:10 and successfully handled multiple requests.
At 02:59:02, the following error started to get logged on every request:
02:59:02.114Z ERROR CrowdStudy: failed to connect to [127.0.0.1:27017]
Error: failed to connect to [127.0.0.1:27017]
at null.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/server.js:555:74)
at emitThree (events.js:97:13)
at emit (events.js:175:7)
at null.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:156:15)
at emitTwo (events.js:87:13)
at emit (events.js:172:7)
at Socket.<anonymous> (/home/ncphillips/Projects/crowdstudy/node_modules/mongodb/lib/mongodb/connection/connection.js:534:10)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at emitErrorNT (net.js:1237:8)
My initial suspicion was that I was that the connection pool was filling up because I don't have anything to handle calling req.db.close(). I thought that passing in the options {auto_reconnect: false} would fix this issue by automatically closing the connection after some time, but it seems I was wrong.
Note that restarting the server fixes the issue, so I believe the problem has to do with Node rather than Mongo.
If this has to do with the connection pool, is there some setting I can pass to fix this, or can I have an end-ware that makes sure the connection always gets closed?
Thanks a lot to anyone who can help me out!
autoReconnect is an option that should be passed to the server configuration:
MongoClient.connect(config.server.db, {
server : { autoReconnect : false }
}, ...);
The documentation contains some errors: it states that the default setting is false (which it isn't), and it also states that autoReconnect should be set in an object called socketOptions (which it shouldn't).
You can add various event listeners to the db object that gets passed back, to detect when the connection to the database got closed/reconnected/...:
db.on('close', function(reason) { ... });
db.on('reconnect', function(db) { ... });
More events here.