Is there a way to use functions from a "double require" - node.js

Sorry if the title is misleading or vague, I couldn't really think of a good way to describe what I'm trying to do.
Basically, I have my index.js file calling another file via a require, we'll say it's js_functions.js.
js_functions.js is calling multiple files via require, and those individual files are all exporting functions correctly.
For sake of example, we'll say that the structure is index.js > js_functions.js > add.js.
Is there a way to call a function from add.js in index.js without directly requiring the add.js in index.js (via js_functions.js)?

If index.js wants to call a function from add.js, then you have two options:
index.js can require('add.js') directly and thus get the exported function from add.js to call.
js_functions.js can export the function from add.js so when you require('js_functions.js'), the function you want to call from add.js is available in the js_functions.js exports.
Generally, I avoid dual exporting as in option #2 and if I want a function from add.js, I just make the dependencies direct and clear require('add.js') so I can get access to that function.
If you're new to node.js module development, then it takes a little getting used to that you start every new module definition, but just adding all the require statements that you need to get access to the modules/functions you need. But, this is how you do module development in node.js and it has all sorts of benefits (testability, resuability, sharability, clear dependencies with no implicit dependencies, etc...). So, just get use to adding a little extra code at the start of each module to import the things you need.
Is there a way to call a function from add.js in index.js without directly requiring the add.js in index.js (via js_functions.js)?
Only if js_functions.js exports the function from add.js that you want to call. Just because js_functions.js has already done require('add.js') that does not provide access to the exports in add.js to any other code besides js_functions.js.
In the future, we can help you more accurately and quicker when you include the actual relevant code. We tend to do a lot better with specific questions that contain specific code than theoretical questions that try to use words (and no code) to describe some problem.

Related

Node.js Globalize es6 modules to act like ImportScripts

The question is simple, how do we make es6 modules act like the ImportScript function used on the web browser.
Explanation
The main reason is to soften the blow for developers as they change their code from es5 syntax to es6 so that the transition does not blow up your code the moment you make the change and find out there are a thousand errors due to missing inclusions. It also give's people the option to stay as is indefinitely if you don't want to make the full change at all.
Desired output
ImportScript(A file path/'s); can be applied globally(implicitly) across subsequently required code and vise-verse inside a main file to avoid explicit inclusion in all files.
ES6 Inclusion
This still does not ignore the fact that all your libraries will depend on modules format as well. So it is inevitable that we will still have to include the export statement in every file we need to require. However, this should not limit us to the ability to have a main file that interconnects them all without having to explicitly add includes to every file whenever you need a certain functionality.
DISCLAIMER'S
(Numbered):
(Security) I understand there are many reasons that modules exist and going around them is not advisable for security reasons/load times. However I am not sure about the risk (if any) of even using a method like "eval()" to include such scripts if you are only doing it once at the start of an applications life and to a constant value that does not accept external input. The theory is that if an external entity is able to change the initial state of your program as is launched then your system has already been compromised. So as it is I think the whole argument around Globalization vs modules boils down to the project being done(security/speed needed) and preference/risk.
(Not for everyone) This is a utility I am not implying that everyone uses this
(Already published works) I have searched a lot for this functionality but I am not infallible to err. So If a simple usage of this has already been done that follows this specification(or simpler), I'd love to know how/where I can attain such code. Then I will promptly mark that as the answer or just remove this thread entirely
Example Code
ES5 Way
const fs = require('fs');
let path = require('path');
/* only accepts the scripts with global variables and functions and
does not work with classes unless declared as a var.
*/
function include(f) {
eval.apply(global, [fs.readFileSync(f).toString()])
}
Main file Concept example:
ImportScript("filePath1");loaded first
ImportScript("filePath2");loaded second
ImportScript("filePath3");loaded third
ImportScript("filePath4");loaded fourth
ImportScript("filePath5");loaded fifth
ImportScript("someExternalDependency");sixth
/* where "functionNameFromFile4" is a function defined in
file4 , and "variableFromFile2" is a global dynamic
variable that may change over the lifetime of the
application.
*/
functionNameFromFile4(variableFromFile2);
/* current context has access to previous scripts contexts
and those scripts recognize the current global context as
well in short: All scripts should be able to access
variables and functions from other scripts implicitly
through this , even if they are added after the fact
*/
Typical exported file example (Covers all methods of export via modules):
/*where "varFromFile1" is a dynamic variable created in file1
that may change over the lifetime of the application and "var" is a
variable of type(varFromFile4) being concatenated/added together
with "varFromFile4".
*/
functionNameFromFile4(var){
return var+varFromFile1;
}
//Typical export statement
exportAllHere;
/*
This is just an example and does not cover all usage cases , just
an example of the possible functionality
*/
CONCLUSION
So you still need to export the files as required by the es6 standard , however you only need to import them once in a main file to globalize their functionality across all scripts.
I'm not personally a fan of globalizing all the exports from a module, but here's a little snippet that shows you how one ESM module's exports can be all assigned to the global object:
Suppose you had a simple module called operators.js:
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
You can import that module and then assign all of its exported properties to the global object with this:
import * as m from "./operators.js"
for (const [prop, value] of Object.entries(m)) {
global[prop] = value;
}
// can now access the exports globally
add(1, 2);
FYI, I think the syntax:
include("filePath1")
is going to be tough in ESM modules because dynamic imports in an ESM module using import (which is presumably what you would have to use to implement the include() function you show) are asynchronous (they return a promise), not synchronous like require().
I wonder if a bundler or a transpiler would be an option?
There is experimental work in nodejs related to custom loaders here: https://nodejs.org/api/esm.html#hooks.
If you can handle your include() function returning a promise, here's how you put the above code into that function:
async function include(moduleName) {
const m = await import(moduleName);
for (const [prop, value] of Object.entries(m)) {
global[prop] = value;
}
return m;
}

Calling auxiliar function from main function working in different routes [Node/express]

I have the following structure in the project:
root
├── models
├── routes
└── controllers
In the routes I specify the route-method pair. Something like this:
router.get('/',verifyToken,controller.getMethod)`
And in the controllers I have the different methods needed.
I have two methods in the same file (controller.js), let's call them aux and main. Method aux is executed in route '/A' and method main is executed in route '/B'.
The thing is that I'm trying to use the aux method inside the main. However, it won't be executed. I am working with morgan and I can see that the only method that is being executed is the main one.
I can't put them together because it is one auxiliar method out of many more that I need, so I need to keep them separated. I'm fairly new to js in general so any tip would be appreciated.
My guess
I think it has to be related to the routes because the main method is being executed as we're in the its route. However, when we try to call the aux method, it won't call the GET request, as we're not in its route.
However, I don't know how to solve this
Your question is a bit hard to understand but lets try to unravel it now.
So if both your methods in different controllers, you can just call the aux file inside main using import or require and use the methods as you need. Just make sure you dont do it in both places as that results in a cyclic dependency error I think.
Maybe if you have some examples or snippets I can guide you better with this. But based on what I read I think you are having issue with calling methods from one file to other, which should be solved on basis of what I mentioned above.
Basically define the blocks of reusable methods/functions that you are using in your route file, OUTSIDE your route file somewhere. Then call that file and use the functions.

How do I find what files use a specific function or file in a Node project, using VSCode?

I'm working with a Node project using VSCode. I'd like to be able to follow the tree upwards from functions/files at a lower level. That is, if I have an exported function doSomething in file dosomething.js, I'd like to see what code calls this function, and/or see what code requires this file.
// index.js
const { doSomething } = require('./tricky-stuff')
// tricky-stuff.js
const doSomething = function() {}
module.exports = {doSomething}
If I'm browsing tricky-stuff.js, is there a built-in feature to VSCode that allows me to see usages of either the function doSomething or where the file tricky-stuff.js is required/imported, so that it would show me the file index.js in this case (as well as perhaps other files where tricky-stuff is used)? Is there any extension? I seem to recall that WebStorm could do this, but I can't remember. (I know I could search for strings, but that seems inelegant).
I think it largely depends on how much VScode knows about your code, via the TypeScript language service or JSDoc comments etc...
Typically you can right click on a function and select the peek all references or find all references options:
In this case, it will show you all the places where that function is called or referenced.

Returning a module in RequireJS

I'm refactoring a large javascript codebase to use RequireJS. Unfortunately, many of the files I'm dealing with are not object-oriented, and cannot return an object without significant modification. Is there a more efficient way to give 'dependent' modules access to the functions and variables contained in a module (without returning an object) ?
I have read about using the exports syntax for defining modules, but it is very unclear whether that would be a valid solution for this situation.
In a defined module, the exports object is what gets exported from the module and passed to whatever module requires it.
Consider this:
define(["exports"], function(exports){
exports.myCustomFunction = function(){};
exports.myCustomObject = {};
exports.myCustomVariable = true;
})
This module will place all the disparate functions and/or objects that you want made public onto the exports object.
At this point RequireJS will use that exports object to pass to a module that requires it:
require(["nameOfCustomModule|filename"], function(myCustomModule){
//evaluates to true
console.log(myCustomModule.myCustomVariable);
})
Here's a simple fiddle. Just bring up your console and you will see the value logged there. http://jsfiddle.net/xeucv/
Hope this clears it up a bit!

Making modules global for use in other files in node.js

I read in another question that i can not find now that it was a bad idea to make modules in node.js global, then he changed his answer because of changes in node.js
The examples for express.js on github does now show an example.
https://github.com/visionmedia/express/tree/master/examples
So what if i need the same module in multiple files, like sequelize or async?
app.js:
var document = require('./routes/document')
async = require('async');
/routes/document.js:
async.series([...]);
OR
app.js:
var document = require('./routes/document')
var async = require('async');
/routes/document.js:
var async = require('async');
async.series([...]);
Should i require the async module again in document.js, or just make async global so that i can use it without require it in new files?
Do not use globals to access modules. Always use require and only require() the modules you need in that .js file. Require will only load your module once and hold a reference to it.
Only requiring what you need, even if it's several modules, is good because it makes it clear what the dependencies of your code are and might help you restructure your code later.
Only requiring() what you need can also help at the point where you want to replace one module with another. For example, you might want to replace knox(S3) with the new aws-sdk module. When you remove the knox npm module, require will immediately blow up in the files that use/require knox. If it was a global variable, you would need to find all references to that global reference and rely on your IDE or text editor to find it.
In short, include it in each file. The file is cached after the first require, so the content is really only run once (you can test this by putting a log statement in the require; it'll only show once).
What I do is make one file which requires all the others I need, and exports them all. Then you only need to require the one file. This can be really handy when you have many modules that you're including.
There is nothing wrong with requiring a module more than once. Internally require only executes the required file once and then caches the result. See the Node.js Modules documentation for more information.

Resources