require index results undefined - javascript

I have two folders next to each other as it follows ..
// Folder 1
users
-services
-index
-otherThings
= services
exports.A = (a,b,c)=> { // do something }
exports.B = (a,b,c)=> { // do something }
= index.js
const services= require('./services');
const otherThings= require('./otherThings');
module.exports = { otherThings, services};
// Folder 2
middlewares
-is-auth
-index.js
= is-auth
const { services } = require('../users');
// services here is undefined
// when i require the full index object it is an empty object
const indexObject = require('../users')
console.log(indexObject) // {}
the weird thing is when using services required above i am getting suggestions of the folder 1 services (A,B functions) but they are undefined !

console log services in folder 1 if it is coming there.
check the hierarchy of your folder structures when importing and
check the paths also,
other wise the code seems right.
edit 1:
not sure what exactly services type are, but it seems only function A and B are there, if you just need those functions you can export them individually and try,
if that works then you can back track to, why services was not working in the first place,
if not, then just try any random variable try importing if it doesn't work then it's may be related to hierarchy.
edit 2:
i think i got it,
if my assumption is right users is folder and services is file, then you need the path as require(../users/services);
edit 3:
then check out this link require folder as a module

Related

JS multiple scopes between files

This answer shows how to share a scope across several JS files.
But I'm wondering how one might go about having two (or more) levels of wider scope, shared between multiple files.
Experimenting, I've found that a slight tweak to the above answer involves sharing an object between files, and then initiating it the first time it is found to be an empty object like so:
var MODULE = (function( widerScopeVariables )
{
if( $.isEmptyObject( widerScopeVariables ) ){
// projectWide:
widerScopeVariables[ 0 ] = {};
// formsWide:
widerScopeVariables[ 1 ] = {};
}
const projectWide = widerScopeVariables[ 0 ];
...
... but the trouble is that projectWide and formsWide (intended to be of more restricted scope) are then both available to every file sharing this MODULE variable, even if by convention you restrict use by files which aren't intended to have access to the formsWide variables.
Furthermore, every file which might be the first to load has to include the above code.
Is there a better way to accomplish this sort of multi-level multi-file scoping in JS?
I have found a sort of way to help accomplish this. It's not elegant, and merely encourages the right kind of use... it will not please JS purists, but it works for me.
For the avoidance of doubt I am aware that JS has only two scopes: global and function.
What I have done is to put a bunch of files in a subdirectory called "generic_elements". Using the design pattern in the answer I referenced I then go like this in these files:
var HOLDER = (function( holderState )
{
const genericDir = getDir( -2 );
const genericWide = holderState[ genericDir ] = holderState[ genericDir ] || {};
...
return holderState;
}( HOLDER || {} ));
where getDir looks like this (global function):
function getDir( pathElement ){
let info = new Error().stack;
const infoLines = info.replace( /\n/g, ' ' ).split( ' ' );
const delimiter = '/';
// [0] or [1] would return the line for this file, not the calling file
const tokens = infoLines[ 2 ].split(delimiter);
// get a directory in this path. -2 means penultimate token = string between penultimate and last '/'
return tokens.slice( pathElement )[ 0 ];
}
... it's not the "full" version in that it only returns the final directory rather than the complete path from the main URL directory.
The idea is pretty simple: a bunch of files in a subdirectory use the path of the subdirectory containing these "files in a module" as a key in the holderState object. They share the object genericWide. Modules higher up can still look at this HOLDER object, but coders (hopefully) agree not to use key-value pairs from modules they know nothing about. Conversely, files in subdirectories will be able to work out the paths of ancestor directories, calling getDir with -3 or -4 or whatever... so they will be able to access their ancestor modules' "directory-wide" objects.

Difference between require('module')() and const mod = require('module') mod() in node/express

I have two files: server.js and db.js
server.js looks as such:
...
const app = express();
app.use('/db', db());
app.listen(3000, () => {
console.log('Server started on port 3000')
});
...
and db.js as such:
...
function init() {
const db = require('express-pouchdb')(PouchDB, {
mode: 'minimumForPouchDB'
});
return db;
}
...
This works just fine, and I am able to reach the pouchdb http-api from my frontend. But before, I had const PouchDBExpress = require('pouchdb-express'); in the top of db.js, and the first line in init() looked like this; const db = PouchDBExpress(PouchDB, {. This gave an error in one of the internal files in pouchdb saying cannot set property query on req which only has getters (paraphrasing).
So this made me copy the exaples from pouchdb-servers GitHub examples which requires and invokes pouched-express directly, and everthing worked fine. Is there an explanation for this? I'm glad it works now, but I'm sort of confused as to what could cause this.
The only difference between:
require('module')()
and
const mod = require('module');
mod();
is that in the second case, you retain a reference to the module exports object (perhaps for other uses) whereas in the first one you do not.
Both cases load the module and then call the exported object as a function. But, if the module export has other properties or other methods that you need access to then, obviously, you need to retain a reference to it as in the second option.
For us to comment in more detail about the code scenario that you said did not work, you will have to show us that exact code scenario. Describing what is different in words rather than showing the actual code makes it too hard to follow and impossible to spot anything else you may have inadvertently done wrong to cause your problem.
In require('module')(), you don't retain a reference of the module imported.
While in const mod = require('module'); mod(), you retain a reference and can use the same reference later in your code.
This problem might be due to some other reason like -
Are you using a some another global instance of the db, and your code works in the given case as you are making a local instance
Some other code dependent scenario.
Please provide more details for the same

Best way to share an instance of a module that is inside a closure [duplicate]

If I want to span my JavaScript project across multiple source files, but have each file have access to the same private variable, how would one do that?
For example, if I have the following code:
APP = (function () {
var _secret = {},
app = {};
// Application part 01:
app.part01 = (function () { /* function that uses _secret */ }());
// Application part 02:
app.part02 = (function () { /* function that uses _secret */ }());
//
return app;
}());
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
I don't want to pass it as an argument. That's just giving the secret away, as app.part01() could be replaced by any other function.
Maybe I am asking the impossible, but your suggestions might lead me in the right way.
I want to work with multiple files, but I don't know how. Copying and pasting everything inside a single function each time before testing is not something I want to do.
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
That's impossible indeed. Script files are executed in the global scope, and don't have any special privileges. All variables that they will be able to access are just as accessible to all other scripts.
Copying and pasting everything inside a single function each time before testing is not something I want to do
What you are looking for is an automated build script. You will be able to configure it so that it bundles your files together, and wraps them in an IEFE in whose scope they will be able to share their private state. The most simple example:
#!/bin/sh
echo "APP = (function () {
var _secret = {},
app = {};" > app.js
cat app.part01.js >> app.js
cat app.part02.js >> app.js
echo " return app;
}());" >> app.js
The only way that you can share _secret is attaching it to the application object and then application object to the window object. Here is an example.
// FIRST JS FILE...
var application; // will be attached to window
(function(app) {
app.secret = "blah!"; // will be attached to application
})(application || (application = {}));
// ANOTHER JS FILE
var application;
(function(app) {
app.method1 = function(){ console.log(app.secret); }; // will be attached to application;
})(application || (application = {}));
console.log(application.method1()); // will display 'blah!' on the console
Working example on jsbin
One way I was able to accomplish this was to create a JS file that contained the global object.
// Define a global object to contain all environment and security variables
var envGlobalObj = {
appDatabase: process.env.YCAPPDATABASEURL,
sessionDatabase: process.env.YCSESSIONDATABASEURL,
secretPhrase: process.env.YCSECRETPHRASE,
appEmailAddress: process.env.YCAPPEMAILADDRESS,
appEmailPassword: process.env.YCAPPEMAILPASSWORD
}
module.exports = envGlobalObj
Then in the files I wish to reference this object, I added a require statement.
var envGlobalObj = require("./envGlobalObj.js");
This allowed me to centralize the environment and secrect variables.

How do I update the values of this variable between modules?

So I have module "bot.js" and in this module, it constantly checks for messages and assigns them to a variable (db_users). Since I run my app from "app.js", and I pass the functions that continuously populates db_users, how do I get this information to "app.js"?
Bot.js is using an IRC function that stores user's messages.
var db_users = []
// I then populate db_users with the previous data that is already in mongodb
// using a .find().exec() mongodb command.
bot.addListener('message', function (from, to, text) {
userInfo.checkForUser(db_users);
// checkForUser basically looks through the variable db_users to see if
// there is a username that matches the "from" parameter in the listener
// If it's not there, push some user information into the db_users array
// and create a new MongoDB record.
}
So I have all this, but my main app is a website that can control this "bot" (It's not a spam bot, but a moderation/statistical bot), and I'm using a require function to use "./bot.js" in "app.js"
app.js
bot = require('./bot');
So how would I constantly use the data in bot.js, in app.js? I'm a little fuzzy on how modules work.
Yeah I could just put all of the contents of app.js in bot.js, but it would be too annoying to look through.
Thanks!
Put db_users inside an object so that it's just a reference. Make changes to that reference instead. Then export that outer object. Now since db_users is just a reference, it'll always be a latest copy of whatever it refers to.
bot.js
var data = module.exports = {};
data.db_users = [];
bot.addListener('message', function (from, to, text) {
userInfo.checkForUser(data.db_users);
}
app.js
botData = require('./bot');
botData.db_users will always have the whatever latest changes were made to data.db_users in bot.js

Is it possible to declare global variables in Node/Express 4.0

I have multiple routes that need to access a database, for development I use a local database, and obviously production I use a hosted database
The only problem is every time I go to push a release I have to go through each route manually changing the database link
e.g.
var mongodb = require('mongojs').connect('urlhere', ['Collection']);
It would be nice if I could declare a variable in app.js like
app.set('mongoDBAddress', 'urlhere');
then in each file do something like
var mongodb = require('mongojs').connect(app.get('mongoDBAddress'), ['Collection']);
Does anybody know if this is achievable I've been messing around with it for about an hour googling and trying to include different things but I have no luck. thanks.
From the docs:
In browsers, the top-level scope is the global scope. That means that
in browsers if you're in the global scope var something will define a
global variable. In Node this is different. The top-level scope is not
the global scope; var something inside a Node module will be local to
that module.
You have to think a bit differently. Instead of creating a global object, create your modules so they take an app instance, for example:
// add.js
module.exports = function(app) { // requires an `app`
return function add(x, y) { // the actual function to export
app.log(x + y) // use dependency
}
}
// index.js
var app = {log: console.log.bind(console)}
var add = require('./add.js')(app) // pass `app` as a dependency
add(1, 2)
//^ will log `3` to the console
This is the convention in Express, and other libraries. app is in your main file (ie. index.js), and the modules you require have an app parameter.
You can add a global variable to GLOBAL, see this this question, although this is probably considered bad practice.
We have two methods in node.js to share variables within modules.
global
module.export
But your problem seems to be different, what I got is you want to connect your application to different databases without changing code. What you need to do is use command line params
For more ref
server.js
var connectTo = {
dev : "url1"
production : "url2"
}
var mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
Run your server.js as
node server.js dev
// for connecting to development database
or
node server.js production
// for connecting to prodiction database
To share connection across diffrent modules
//Method 1
global.mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
//Method 2
exports.mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
exports.getMongoDBAddress = function() {
return connectTo[process.argv[2]]
}

Categories

Resources