Node: Proper place to require database config - node.js

What my team has been doing: server.js requires server-config.js (Express routing, API requests, etc), which requires query.js (where my Mongoose MongoDB schema is defined) which in turn requires db-config.js (where I actually connect to Mongo). Then in my db-config I have to require the query.js Schema anyways, which creates a cyclic dependency.
Wouldn't it be better just to require db-config instead of query.js inside of server-config? That way, the database connection is started and then the cyclic dependency is broken.

Related

Manage Connection in Mongoose across Modules

I am creating a Node Module which will perform some databasebase queries using mongoose. What I want is to access the mongoose connection variable across the module which is created in the main application. I have read that Mongoose is a singleton object to I guess it should work but it isn't working at all. ANy help will be appreciated

How to use mongoose in two packages?

I'm using Lerna to handle multiple packages in my repo.
Basically, I have a package #pkg/server where my Node/Express App is and an other package #pkg/model where my mongoose Schemas reside.
My REST API is using some of the models, with an import ModelA from '#pkg/model'.
The problem is that both of these packages have mongoose as a dependency (the #pkg/server uses mongoose to establish a connection to the mongoDB server, and #pkg/model uses mongoose to define schemas and models).
In my server, whenever I try to call ModelA.find(...), it just hangs forever. From the mongoose docs, it looks like I have to register a model to a mongoose connection and not to the mongoose object itself.
My first guess is to pass the connection object created by the server to the #pkg/model and then register the models to this connection object.
My question is, is this the right way to do it? Or is there a way to do something like (in the #pkg/server) mongoose.loadSchemas(#pkg/model) ?
What I have ended up doing, is that I'm passing the connection to the package requiring mongoose thus sharing the connection between packages.
Some package can register models, an other one can make queries, etc...

How can I pass a library to a lower dependency in node?

I'm trying to create a library that uses the ORM Bookshelf.js (so basically a wrapper on top of Bookshelf.js if you will). Now Bookshelf.js requires you to run a driver installation to be able to connect to the correct database (such as: npm install mysql) in the root of your project.
My own library also requires this, since Bookshelf.js requires it, but it keeps saying Error: Cannot find module 'mysql' which is normal since the Bookshelf instance does not have the mysql dependency in its node_modules folder.
If I type out the structure it would look like this:
* New Project
** mysql
** LibThatUsesBookshelf
**** Bookshelf
Now Bookshelf.js probably requires this structure:
* New Project
** LibThatUsesBookshelf
**** mysql
**** Bookshelf
Is there a way that I am able to still get bookshelf working with the first structure shown?
P.S. I know the explanation might be confusing, but it is a hard problem and I got no other way of explaining it.
Let the client of your module pass in an instance to bookshelf:
// mysuperfancymodule.js
module.exports = function(bookshelf) {
// do fancy things with the bookshelf instance
}
Then in your client application:
// some app code:
var mySuperFancyModule = require('mysuperfancymodule'); // assuming it is published to npm
var knex = require('knex')({
// init knex...
});
var bookshelf = require('bookshelf')(knex);
mySuperFancyModule(bookshelf); // init my super fancy module

node express postgres - why and how to connect to database using pg module?

I am super new to node express and postgres and wondering the following:
const pg=require('pg').native
const client=new pg.Clirnt('postgres ...')
what is const?
pg is used to create a client to connect to the Postgres database-correct?
If so
var db = new Sequelize('postgres://localhost:5432/mydb')
would work too or would I just have created a database without connecting it?
Why exactly do I need to connect at all-to do what?
Thanks a lot!
const is constant in javascript which was introduced in ES6 specification.
node-postgres is a client for PostgreSQL.
Sequelize is using node-postgres for working with PostgreSQL database, so yes, in the nutshell, it will act like node-postgres.
Imagine the warehouse, that's your database, where you have different shelves, that's your tables, to take or put different items into warehouse you need workers that will do your instructions like - INSERT someitem INTO items_shelf;. So worker is the client like Sequelize or node-postgres. The important part, warehouse should be open, otherwise, workers couldn't access to it, so your database should be turned on.
Hope I'm explained understandable enough.
what is const?
TLDR; variables that can't be re-assigned. scoped the same way as var. Part of es6.
pg is used to create a client to connect to the postgres database?
yes, note you need to do npm install --save pg as well as npm install --save sequelize. the save flag adds the packages to the package.json file for your convenience.
would I just have created a database without connecting it?
That bit of code should instantiate a connector - you haven't modified the database, and you also don't really know if the connection works yet.
why exactly do I need to connect at all?
The pg library looks to use a connection pool; this means you set it up once, and then you use it repeatedly as desired and it handles the connections for you. You connect now so you can run queries against the database later.
This snippet of code connects to a postgres instance running locally on my machine, and tests that it can connect - per the docs
const Sequelize = require('sequelize');
var sequelize = new Sequelize('postgres://localhost:5432/postgres');
sequelize.authenticate().then(() => {
console.log('yay');
}).catch((e) => {
console.log('nooo', e);
});

Sharing a Mongoose instance between multiple NPM packages

In an attempt to modularize a large existing Node+Express+Mongoose
application into multiple mountable apps, each developed as a
separate NPM package, we're wondering whether sharing a single
Mongoose instance between them is a good idea?
Let's say we have a suite of NPM packages each containing client-side assets,
Mongoose models, and a REST-API implemented with Express. They do share
a few common traits but are essentially to be considered separate
reusable artefacts. A host application, also Express-based, mounts these
under various root URIs:
var discussions = require('discussions'),
tickets = require('tickets'),
events = require('events'),
express = require('express'),
app = express();
var environment = { ...see below... };
...
app.use('/events-api', events(environment));
app.use('/tickets-api', tickets(environment));
app.use('/discussions-api', discussions(environment));
Now, since the events, tickets and discussions apps (separate NPM packages
pulled in via the host package.json) use Mongoose, as do the
host application itself, we figured we would pass in the host Mongoose instance
through some kind of environment object that also include other
stuff that the host wants to share with the mounted apps.
Do you see any obvious flaws with this approach? The mounted apps
in this case would not specify Mongoose as a dependency in their
respective package.json, and they would not require('mongoose')
as normally done but instead get the Mongoose instance from the host
which is responsible for connecting it to MongoDB.
If this is a bad idea and you suggest each sub-app declare a dependency
towards Mongoose on their own, each NPM package would get their own
copy of Mongoose and would each have to connect to MongoDB, right?
Some background info:
We really do want to include the apps in a host application, running
in a single process, rather that having multiple Node instances. The
host contains middleware for authentication and other things.
We do want to have the apps as separately developed NPM packages included
as versioned dependencies of the various host applications that we build,
rather than just copying their source to a host application.
We realize that reusing the same Mongoose instance between multiple
mounted apps will have them share the same model namespace.
Edit: To clarify the package structure after all has been npm installed:
host/
assets/
models/
routes/
node_modules/
express/ ...
mongoose/ ...
events/
assets/ ...
models/ ...
routes/ ...
tickets/
assets/ ...
models/ ...
routes/ ...
discussions/
assets/ ...
models/ ...
routes/ ...
That is, the events, tickets, and discussions apps do not include
Mongoose (or Express) of their own but are designed to rely on an always-present
host application that suppliesd those dependencies.
We're assuming here that an NPM package like tickets cannot simply
require stuff from the parent, right?
If you want to reuse your Mongoose package between other NPM packages, the best way to do it is to install the shared package at the top level app and then use it to initialize the other NPM packages.
In the top level:
var db = require('myMongooseDb'),
events = require('events')(db),
...
Then your events package just needs to export a function that takes the db as a parameter.
I suggest you have a look at https://github.com/jaredhanson/node-parent-require, a recently published package which solved this issue for me.
The node-parent-require Readme file on the Github project page provides a detailed walkthrough using mongoose.
Basically, you need to dig in your submodule and replace this:
mongoose = require("mongoose");
... with this:
try {
var mongoose = require('mongoose');
} catch (_) {
// workaround when `npm link`'ed for development
var prequire = require('parent-require')
, mongoose = prequire('mongoose');
}
Don't forget to add mongoose as a peerDependency in your submodule's package.json. For example:
"peerDependencies": {
"mongoose": "3.x"
}
You may also want to read http://blog.nodejs.org/2013/02/07/peer-dependencies/ first.
const mongoose = require('mongoose-global')();
You can just require one global mongoose instance and use it anywhere.
https://www.npmjs.com/package/mongoose-global

Resources