get referring script file in nodejs - node.js

In Node JS, Is it possible to determine which script is requesting the current module? In other words, who is requiring the current script?
example:
index.js is requesting helper.js.
In helper.js, how can console.log(some_referrer) == '/path/to/index.js')

No, it's not possible. In fact helper.js could be required from many different scripts, but will only ever be executed once. Any time another script requires it, it will just return whatever was assigned to module.exports from the first time helper.js was included directly, without executing helper.js again.
You can, however, determine the original script that was run, using require.main. That won't tell you whether index.js required other.js which required helper.js or, index.js required helper.js directly. But it does tell you that index.js was the original script that was executed directly.
If you want helper.js to have different behaviour depending on how it is called, you could also export a function from helper.js and expect the script that requires that function to call it and pass it an argument:
// helper.js
module.exports = function ( arg ) {
// Use arg to determine which action to take.
};
// index.js
require( 'helper.js' )( 1 );
// other.js
require( 'helper.js' )( 'other' );

Assuming all files are in the same path.
Module1.js
console.log('required from --> ', require.main.filename);
Module2.js
var module1 = require('./Module1');
Then exec.
$ node Module2
$ required from --> /path/Module2.js
But if you add
Module3.js
var module2 = require('./Module2');
Then.
$ node Module3
$ required from --> /path/Module3.js
So, basically you can't, except if the script you are executing (main script) is the same which is requiring your Module1.

Figured out I can evaluate require.main === module. Good things happen when you rtfm :)
https://nodejs.org/api/modules.html#modules_accessing_the_main_module

Related

How can I run a Typescript script on Node without importing anything from it?

Typescript handbook mentions scripts, as opposed to modules:
Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
I have a couple of scripts that don't import anything, just iteratively do some work, like this:
// script.ts
console.log('test')
I want to run them all one by one from the index.ts (which is defined as main in package.json). However, when I just import them:
// index.ts
console.log(1)
import {} from './script'
console.log(2)
It does not do anything in the compiled JS:
// index.js (compiled)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
console.log(1);
// << shouldn't there be something here?
console.log(2);
//# sourceMappingURL=index.js.map
How can I properly call that script so it root content runs when I run my compiled index.js?
Scripts are imported like this:
import './script'
without using from

How can I keep "require" working for dynamic expressions

I want to bundle a Node.js script, which somewhere calls require(expression). After bundling the script with webpack, require fails. This is a super simplified example:
// main.js
const x = require(process.argv[2])
console.log(x)
I would like to either have a "normal" require for this case or tell webpack to include a specific file which I know will be required in the future (after bundling). To stick with this example, I know the value of process.argv[2] ahead of bundling.
Note: The code doing the expression based require is a dependency, so I cannot tweak require code.
This is my webpack.config.js
module.exports = {
entry: './test.js',
output: {
filename: 'test.js'
},
target: 'node'
}
The require path is relative to the file it is used in. So you'll need to figure out the path from where require is executing to the file it's loading from the parameter. Then prepend the relative part to the parameter.

Node.js - "Cannot find module", when the module call other module

I'm developing my first Node.js App. and Everything is find, but Now the app is getting bigger. and I'd like to divide the app into different files. So, I used a "require" method to divide a app into files.
but My App display "Cannot find module".
** Call Ordering **
A.js is call B.js <-- call is ok
B.js is call C.js <-- Cannot Find module, B.js can't call 'test222 function'
My Sample Code.
a.js
...
var m=require('./controller/b.js');
m.register(req,res);
b.js
exports.register=function(){
var MyModule=require('./model/c.js');
console.log(MyModule.test222()); <--------- cannot find module
};
c.js
exports.test222=function() {
return "c.js";
};
Help me or advice. thank you.
I want to Call module in another module. but My Node App is not working for "cannot find module". How to solve it?
It seems that you've mistyped by writing var m=require('./controller/a.js'); instead of var m=require('./controller/b.js');
If so, I can see that you have the following file structure:
./a.js
./controller/b.js
./model/c.js
So you run ./a.js which requires ./controller/b.js and it works fine. But when ./controller/b.js requires ./model/c.js, Node resolves c.js as ./controller/model.js, because each module is relative to the file calling require().
This is why error occurs.
To solve this problem you should replace
var MyModule=require('./model/c.js');
with
var MyModule=require('../model/c.js');
the require function automatically search for modules at the node_modules folder
by just typing the name of the module with the js. extension
var b=require('b.js');
var c=require('c.js');
but if you make changes to the structure of your node_modules folder you need to navigate to your moduleusing the relative waie by taping
"../"
to navigate from a child directory to the parent directory and
"./"
to navigate from the parent directory to the child directory
You need to respect the relative way.

what gets called first when a directory is treated as a function?

The open source blogging project Ghost has an index.js file with just this code in it.
// # Ghost bootloader
// Orchestrates the loading of Ghost
// When run from command line.
var ghost = require('./core');
ghost();
If you run node index.js, it starts the application. The ./core in the require statement is actually a directory with a lot of sub-directories in it, so this index.js file is essentially calling the whole directory (which has many functions and files in it) as a function ghost();, which begs the question, what is actually being called first when ghost(); happens? Will it automatically look for an index.js file inside the /core directory?
For example, inside ./core, in addition to a bunch of other directories, there's also this index.js file with one function in it startGhost
// # Ghost bootloader
// Orchestrates the loading of Ghost
// When run from command line.
var config = require('./server/config'),
errors = require('./server/errorHandling');
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
function startGhost(app) {
config.load().then(function () {
var ghost = require('./server');
ghost(app);
}).otherwise(errors.logAndThrowError);
}
module.exports = startGhost;
so my question is, when there's a setup like this where a whole directory is called like a function
var ghost = require('./core');
ghost();
is node's default to look for an index.js file inside ./core, and, in this case, call startGhost?
The way I understand it is that
var ghost = require('./core');
ghost();
and
var ghost = require('./core/index.js');
ghost();
are equivalent. In other words, requiring a directory is just short hand for requiring the index.js in that directory.
To deal with the second part of your question, your index.js exports a function. This means that when you require index.js your variable will contain a function with you can then call, in your case with ghost().
It is important to understand that modules don't have to export a function, they can export an object and other things as well. This post explains it well.

PhantomJS require() a relative path

In a PhantomJS script I would like to load a custom module but it seems relative paths do not works in PhantomJS ?
script.js:
var foo = require('./script/lib/foo.js');
foo.bar('hello world');
phantom.exit();
foo.js:
exports.bar = function(text){
console.log(text);
}
According to fs.workingDirectory I am in the good directory
foo.js is not in the lookup path of phantomjs
Am I missing something ?
EDIT:
inject() is not revelant because I do not need to inject a JS to an HTML page but instead load my own module like require('fs') but with a relative path.
After a lot of time searching for the same thing, here is what I understood, though I might be wrong :
PhantomJS doesn't use Node's require, but its own require, so things are different
when providing a relative path to phantomjs's require, it is always interpreted as relative to the current working directory
PhantomJS doesn't implement node's __dirname, and as such there is no direct way to have the directory of your script
The solution I found least annoying :
if using phantomjs pure, without casperjs :
require(phantom.libraryPath + '/script/lib/foo.js')
if using casperjs :
var scriptName = fs.absolute( require("system").args[3] );
var scriptDirectory = scriptName.substring(0, scriptName.lastIndexOf('/'));
require(scriptDirectory + '/script/lib/foo.js')
To load your own module, the right way to do it is to use module.exports, like this: foo.js
function bar(text) {
console.log(text);
}
exports.bar = bar
And in script.js (which is executed with phantomjs script.js):
var foo = require('./script/lib/foo');
foo.bar('hello world');
phantom.exit();
My solution to load a resource file (like let's say a json file) within a phantomjs subfolder from a outer folder like in this structure:
├── consumer.js
├── assets
├── data.json
├── loader.js
Supposed that data.json must be load by the consumer module and that this module is called by somewhere else on this machine, outside the project root folder, the fs.workingDirectory will not work, since it will be the path of the caller file.
So to solve this, I did a simple loader module within the assets folder, where the files I want to load are:
(function() {
var loader = {
load : function(fileName) {
var res=require('./'+fileName);
return res;
}
}
module.exports=loader;
}).call(this);
I therefore call the loader module from the consumer module like
var loader=require('./data/loader');
var assets=loader.load('data.json');
and that's it.
NOTE. The require here is the phantomjs require not the node version, so it works a bit differently. In this case the data.json was a json array with no module.exports declaration. The array will be backed in the assets variable directly when calling the loader.load(fileName) method.
have you tried to use injectJs(filename)
excerpt form PhantomJS documentation:
Injects external script code from the specified file. If the file can
not be found in the current directory, libraryPath is used for
additional look up.
This function returns true if injection is successful, otherwise it
returns false.
Which PhantomJS version are you running? Support for user provided modules was added in 1.7.

Resources