Node require executes code twice for mongoose Schemas - node.js

I am having trouble with require executing my code twice. Working on a standard Express app I build Mongoose Schemas, each in it's own files and export them.
//user.js
const User = mongoose.model('User', userSchema)
module.exports = User
//In other files
const User = require('../models/User')
Now I use this in two places in my application and get an error saying that
Cannot overwrite `User` model once compiled.
So the code above is getting called twice as it is the only code right now creating a model. However I would expect Node to only execute it once since it is required in my code.
The really strange part is that checking out an earlier version from Git I get the same error and people working with me on this get the same error. So I have no more ideas where to look for solutions.

Found the solution now.
Turns out I required the module once as models/user and once as model/User which in the cache of require creates two separate modules.
There have been many discussion about this:
one issue
another issue
old PR
It seems that this is due to Windows resolving paths case insensitive while other systems resolve paths case sensitive and node therefore doing it sensitive.
And a new module of'cause gets executed. Simply requiring is both times spelled in lowercase solved the issue.

I think the problem is in "const" that you use to declare the variable "User".
Try to use "var" instead of .
//user.js
var User = mongoose.model('User', userSchema)
module.exports = User
//In other files
var User = require('../models/User')
P/S: This is link that clarify more about "const" and "var":
Const in javascript? When to use it and is it necessary
Hope it helpful for you !

Related

module.exports = app More than One Require

I'm creating a lambda function on AWS and I'm looking to require more than one file for "app". Apologies, I'm not great with Node yet.
In a routes.js file I have the following...
module.exports = app => {
require("./event.routes.js")(app);
require("./eventtemplate.routes.js")(app);
};
Normally there is only 1 require() between the {}. But I require both files as I've separated out the code into two different files for clarity. When I comment out the second require all is good and the runtime can find the functions in event.routes.js. But with the second require in there. It does not. Do I need to somehow name them? They do have similarly named functions. But they are contained within their "Event" and "EventTemplate" object in those different files.
Here's the event.routes.js file...
module.exports = app => {
const controller = require("../controllers/event.controller.js");
// Create a new event
app.post("/event", controller.create);
};
My eventtemplate.routes.js has similarly named functions. So I'm guessing this is the issue. My attempt to make things cleaner has broken things. Wondering if there is a better way to separate out things?
** UPDATE **
As requested, here is eventTemplate.routes.js...
module.exports = app => {
const controller = require("../controllers/eventtemplate.controller.js");
// Create a new EventTemplate
app.post("/event/template", controller.create);
);
I solved the issue. It was just that I had a misnamed function in my controller file that was being referenced from my route file. I had truncated the source listing for brevity but I would've had to post the controller code as well to see the error.
However thanks for the comments. It did steer me in the right direction to know that what I was doing was fine and correct and was just a typo. Thank you!

node populatedb url not working

I am learning ExpressJs tutorial from https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose
Now I have created module for mongodb database and then create a file populatedb.js in the root directory. Now I am trying to connect to database using command (as describe at last on above link)
node populatedb mongodb://dbuser:dbpassword#ds133814.mlab.com:33814/local_library_tutorial
but terminal response nothing and there doesn't happen in database
My Brother.
I ran into the same problem, and when my search led me to your question i was even more sad when I saw no answer, however after searching around, I found an answer!
Make sure you replace the "dbuser:dbpassword" placeholders with actual data e.g "Elias:js44889" on your mongo url.
Also just make sure it's also the same as the one in app.js.
I think all should be fine as it was for me.
you must include the script in populatedb.js to get work done.
populatedb.js script link : https://raw.githubusercontent.com/hamishwillee/express-locallibrary-tutorial/master/populatedb.js
After inserting the script in populatedb.js file from above link, then run the following commands to populate data in mongoDB.
npm install async (if not installed async module)
node populatedb <your mongodb url>
sometimes you may get an error if you use the same collection name in all of your models, this happened to me until i realised what i was doing was wrong.
for example don't do this
const authorModel = mongoose.model('author', AuthorSchema)
const bookModel = mongoose.model('author', BookSchema)
if you do it un-expeectedly it will throw this error
OverwriteModelError: Cannot overwrite author model once compiled.
instead in the commandline for "windows users" write
node populatedb mongodb+srv://username:password#yourcluster.mongodb.net/yourdatabase
and in your models make sure that the collections are not the same
const authorModel = mongoose.model('author', AuthorSchema)
const bookModel = mongoose.model('book', BookSchema)
I also ran into the same issue as I am doing the same tutorial. What I did to resolve this issue is go to the populatedb.js link they provide in the first step of the "Testing - create some items" or you can download it. Once I clicked on the link, they provide test data that you can paste into the populatedb.js file you've created in the root of your project then:
npm install async --save
node populatedb <your mongodb url>
Script should run and you should see the results or items as it creates them.
Followed the MDN tutorial, Here is what I fixed:
username:Jeff ; password : 12345
app.js, change to:
var mongoDB = 'mongodb://Jeff:123#ds149732.mlab.com:49732/local_library';
Command Line prompt, change to:
node populatedb mongodb://Jeff:12345#ds149732.mlab.com:49732/local_library
Posting here because this answer is the result I found googling the problem.
Had the same problem, the error ended up being the password I have set for the admin on the database - special characters were encoded (there was a warning displayed which I apparently ignored) which caused me to not be able to connect.
I had this issue for a couple of days with the error
zsh: no matches found: <my mongodb url>
First, I double checked I had followed the instructions in Testing — create some items in the tutorial.
Then I changed my original mongodb URL in the terminal, removing the end.
My original mongoURL =
mongodb+srv://username:password#cluster0.9f24o.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
My new mongoURL =
mongodb+srv://username:password#cluster0.9f24o.mongodb.net/myFirstDatabase
I ran this script while in my express-locallibrary tutorial folder.
node populatedb mongodb+srv://username:password#cluster0.9f24o.mongodb.net/myFirstDatabase
I'm not sure at this point if this means I need to change the link in app.js as well.
Hopefully this saves someone some time!

What is the best way to separate your code in a Node.js application?

I'm working on a MEAN (Mongo Express.js Angular Node.js) CRUD application. I have it working but everything is in one .js file. The single source code file is quite large. I want to refactor the code so CRUD functionality is in different source code files. Reading through other posts, I've got a working model but am not sure it is the right way in Node using Mongo to get it done.
Here's the code so far:
<pre>
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var path = require('path');
var db;
var connect = 'mongodb://<<mddbconnect string>>;
const MongoClient = require('mongodb').MongoClient;
var ObjectID = require("mongodb").ObjectID;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/'));
// viewed at http://localhost:<<port referecnes in app.listen>>
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'));
});
MongoClient.connect(connect, (err, database) => {
if (err) return console.log(err)
db = database
app.listen(3000, () => {
console.log('listening on 3000' + Date() );
// Here's the require for the search function in another source code file.
var searchroute = require('./serverSearch')(app, db);
})
})
//Handlers
The rest of the CRUD application functions with app.post, app.get. These are other functions I want to move into different source code files, like serverSearch.js.
</pre>
The code I separated right now is the search functionality which is inside of the MongoClient.connection function. This function has to successfully execute to make sure the variable 'db' is valid before passing both variables 'app' and 'db' to the the search function built out in the source code file serverSearch.js.
I could now build out my other CRUD functions in separate files in put them in the same area as 'var searchroute = require('./serverSearch)(app,db);
Is this the best way to separate code in a MEAN application where the main app and db vars need to be instantiated then passed to functions in other source code files?
What you are basically describing is modular coding heading towards "services" perhaps even micro-services. There are a few factors to keep in mind for your system. (I have no doubt that there are many other approaches to this btw). Basically in most NodeJS systems I have worked on (not all) I try to apply the following architecture in development and then bring over as much as possible I to production.
Create a directory under the main one. I usually use some type of name that points to the term functions. In this directory I maintain function and /or class files divided into categories. Function wrappers for DB would be held in DB functions. This file would only contain functions for the DB. Security functions in another file. Helper functions in another. Time manipulation in another. I am sure you get the idea. These are all wrapped in module exports
Now in any file in my project where say I would need DB and helpers I will start it by:
let nhelpers = require("helpfuncs");
let ndb = require("dbfuncs");
Obviously names are different.
And btw I divide all the NPM packages in the same way under an environment directory.
Maintaining that kind of structure allows you to maintain sane order over the code, logical chaining in any decent IDE, and having relevant methods show up in your IDE without having to remember every function name and all the methods within.
It also allows you to write an orderly system of micro-services making sure each part dies exactly what you want and allows for sane debugging.
It took me awhile to settle on this method and refine it.
It paid off for me. Hope this helps.
Edit to clarify for the OP:
When it comes to the process.env variables I became a great fan of dotenv https://www.npmjs.com/package/dotenv
This little package has saved me an incredible amount of headaches. Of course you will have to decide if you include it in production or not. I have seen arguments for both, but i think in a well set up AWS, Google, Azure environment (or in Docker of course) I am of the opinion it can safely be used.
A couple of caveats.
Do not leave your dotenv file in the root. Move it somewhere else in your directory structure. It is simple and I actually put it in the same directory as all my environment files and helper files.
Remember it is simply a text file. So an IDE will not pick up your specific env variables in chaining. (Unless someone knows of a trick which I would love to hear about)
If you put env variables like access info to your DB system or other sensitive stuff, HASH THEM FIRST, put the hash in your env and have a function in your code which specifically just does the hash to the string. Do not under any conditions leave sensitive information in your environment file without hashing it first.
The final Gatcha. These are not PHP magic globals which cannot be overwritten. If you lose track and overwrite one of those process.env variables in your code it will take the new value until you restart your node app and it reads from the dotenv file again. (But then again that is the rule with all environment variables not only user defined ones)
Any typos above excuse me. Done from my cell in the train.

Problems running KeystoneJS without MongoDB

I would like to try running KeystoneJS without MongoDB.
There's a short blog post explaining how to do it at http://ifrederik.com/blog/2014/11/cms-without-db-running-keystonejs-without-mongodb/
Basically, it explains how to replace MondgoDB with TingoDB and using a Tungus driver.
The advice is to put the following into the top of the keystone.js file
global.TUNGUS_DB_OPTIONS = { nativeObjectID: true, searchInArray: true };
var tungus = require('tungus');
var mongoose = require('mongoose');
And later to set mongo database url to TingoDB.
keystone.set('mongo', 'tingodb://'+__dirname+'/data');
By doing this I got KeystoneJS up and running. By inspecting the contect of data/users file in TingoDB I can even see that the default user gets created, but I was not able to log in. It always reports that username / password combination is not ok.
What am I missing? How do I debug the problem to find out what exactly is the problem here?
Ok, to asnwer to myself, the problems seems to be because User.modele.findOne({email: emailRegExp}) doesn't work in TingoDB/Tungus.
When replaced it with lookup.email, without using regex-es, it semms to work.
But who knows if and what else will break because of incompatibility.

Nodejs + CoffeeScript + Mongoose : Define Module?

I'm trying to create a little application to store snippets of code using nodejs and mongodb
I'm using Coffeescript to write the app.
The problem is, i want to separate the code in modules
so i create this folder structure
/app
/lib
/models
/routes
core.coffee
The core.coffe is the "server" app using expressjs
so in this file i have
mongoose = module.exports.mongoose = require 'mongoose'
app = module.exports.app = express.createServer()
Snippet = module.exports.Snippet = require __dirname+'/lib/models/Snippet'
#App configurations
routes = require(__dirname+'/lib/routes/general')
In lib/models/Snippet
mongoose = module.parent.exports.mongoose
Snippet = new mongoose.Schema
title:
type: String
default:'Title'
mongoose.model 'Snippet',Snippet
exports.Snippet = mongoose.model 'Snippet'
In /lib/routes/general.coffee
app = module.parent.exports.app
mongoose = module.parent.exports.mongoose
Snippet = module.parent.exports.Snippet
app.get '/test', (req,res)->
snip = new Snippet()
res.send snip
But this don't work i get the following error message
TypeError: object is not a function
at Object.CALL_NON_FUNCTION_AS_CONSTRUCTOR (native)
How can I accomplish that?
I see a noteworthy typo:
Snippet = module.exports.Snippt = require __dirname+'/lib/models/Snippet'
Change module.exports.Snippt to module.exports.Snippet.
Let's start by looking at how you're using require. It looks like you're trying to load all the project's requirements in core.coffee, and then re-export them elsewhere. That's an odd way of doing it, most people just require those libraries in each module that needs them (for now at least, see the end of my answer).
For example, you need mongoose in lib/models/Snippet, so just require it there:
lib/models/Snippet:
mongoose = require 'mongoose'
Next, there's no need to use __dirname to require a relative path, require copes fine with a path starting with ./:
require './lib/models/Snippet'
I still wasn't able to get the code to work cleanly (I'm guessing we're not seeing the full code), but it might be enough to set you on the right path.
Finally, if you want to go down the route of exporting everything on the main module can I suggest taking a look at dave-elkan's layers project. The plain version doesn't support coffeescript, but I've created a fork that does.
It's very lightweight, and makes almost no assumptions about your project structure. The basic idea is that you give layers() your express app object and a directory. Layers will scan that directory and set up any subdirectories as layers on your app object.
In your case you'd pass in a rootPath: __dirname + '/lib' and your app object would get app.models.Snippet and app.routes.general added onto it. That's still not quite how I'd structure it, but you might be able to come up with something that matches your style from there.

Resources