what gets called first when a directory is treated as a function? - node.js

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.

Related

How to access the base package form a node_module

I am looking to access a JSON config file that the user would place next to their package.json from a node_module package that I created. Is there a best approach to do this. I tried a relative import but that didn't really work and I am not sure how best to accomplish dynamic imports if the config file doesn't exist because I want to allow it to not exist as well.
Here is how I tried to handle dynamic imports though:
export const overrides = (function () {
try {
return require('../../../../../../overrides.json');
} catch (_err) {
return null;
}
})();
Also I tried fs but I get a browser config error I am not sure if that is something else. I should research but I didn't understand the docs around that.
using a library
This worked for me: find-package-json
Basically on any js file who needs the base, home or workspace path, do this:
var finder = require('find-package-json');
var path = require('path');
var f = finder(__dirname);
var rootDirectory = path.dirname(f.next().filename);
rootDirectory will be the location of the folder in which the main package.json exist.
If you want to optimize, get the appRootPath variable at the start of your app and store/propagate the variable to the hole nodejs system.
no libraries
Without any library, this worked for me:
console.log("root directory: "+require('path').resolve('./'));
This will get you the root directory of your nodejs app no matter if you are using npm run start or node foo/bar/index.js
More ways to get the root directory here:
Determine project root from a running node.js application
usage
If you achieve to obtain the root directory of your nodejs app and your file is at the package.json level, use this variable like this to locate any file at root level:
rootDirectory+"/overrides.json"

How to create a config file for node pkg

I use node pkg to create a .exe of my nodejs service: https://www.npmjs.com/package/pkg
My question is: how do I make the .exe use a config.js for some setup values? Basic stuff like ip, port, database name etc. Because I have 3 environments, and I would like to use the same exe for all, but different config.js files for each.
So far, if I do pkg app.js then it creates an .exe that doesn't look at any other files. Totally stand alone. How do I make it look at config.js when it is started up?
On the website they do have a section on config https://github.com/zeit/pkg#config but I do not understand how to make use of it. At the moment I have my app.js, and I have secrets.js which holds the config information.
I am not sure this is right way, but I hope this can be helpful to somebody.
Refer to pkg document, on the run time, __dirname becomes "/snapshot/project".
So, by checking __dirname, you can identify in which environment you are.
(node app.js or app.exe).
Then we can separate require sentence like below.
const PKG_TOP_DIR = 'snapshot';
const runInPKG = (function(){
const pathParsed = path.parse(__dirname);
const root = pathParsed.root;
const dir = pathParsed.dir;
const firstDepth = path.relative(root, dir).split(path.sep)[0];
return (firstDepth === PKG_TOP_DIR)
})();
let config = require('./appconfig.json');
if(runInPKG) {
const deployPath = path.dirname(process.execPath);
config = require(path.join(deployPath, 'appconfig.json'));
}
Adding above code to your app.js makes some warning when pkg build.
pkg . --targets node8-win-x64 --out-path ./dist
pkg#4.4.0
Warning Cannot resolve 'path.join(deployPath, 'appconfig.json')'
app.js
Dynamic require may fail at run time, because the requested file
is unknown at compilation time and not included into executable.
Use a string literal as an argument for 'require', or leave it
as is and specify the resolved file name in 'scripts' option.
https://github.com/vercel/pkg/issues/195
use fs to read config file insead of require or import
eg:
const configPath = path.join(process.cwd(), './config/config.json');
lset data = fs.readFileSync(configPath);
same question link:excluding config file while converting node js files to exe using pkg

get referring script file in nodejs

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

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.

Node get path of the requiring parent file

I'm writing a node module and need to read a file in the same directory as the file which requires my module.
For instance, I have app.js and in the same folder, template.html.
In some unknown directory is module.js and app.js requires it.
How can I read template.html from module.js?
Inside your file you will have a module global (not actually a global)
you can get the parent object using module.parent and the filename with module.parent.filename then you could extract the folder
so from from your module.js you can use module.parent.filename.
http://nodejs.org/api/modules.html
p = require('path')
template = p.join(p.dirname(module.parent.filename),'template.html')
And if you are looking for the path of the file which was executed then you can use require.main.filename
Have a look here: http://nodejs.org/docs/latest/api/globals.html#globals_dirname
The you can just do this from within app.js:
var path = __dirname + '/template.html';
Then you can send this path to your module.js via some function or API.
Then your module can just use this path.
Inside a "module.js", the trick is using module.parent.filename
I don't personally like using globals, and for certain files (like configuration or templates), managing module require stack isn't so hard.
module.parent is mapped to the parent requiring module (which could be app.js as in your example).
Combining module.parent.filename with the path module gets you a few useful things like:
var path = require('path');
var parent_path = path.dirname(module.parent.filename);
var parent_relative = path.resolve(path.join(parent_path, '../', 'view'));
var template = path.join(parent_path,'./views/template.html');
I don't like using globals for anything to do with paths, I get spagetti ../../../dir./s

Resources