get path of the file the module is being called from? - node.js

Let's say I have a node.js module
module.exports = function () {
console.log(__filename);
}
And in the main file I call it like
var x = require('path/to/module');
x();
That gives me the path to the module file. For example if I stored the module at ~/project-root/lib/mod.js and the main.js file lies at ~/project-root/main.js, that setup gives me the output:
~/project-root/lib/mod.js
I want to use something in place of __filename in the module that gives me to location of of the file from which it was called from. (e.g. the output would be ~/project-root/main.js instead, in this example).
The module can be located anywhere. So using path to adjust for only this example would fail in other scenarios (for example if module is stored in ~/project-root/node_modules/ or the global node.js modules directory.
I have a feeling it's something fairly trivial and I'm overlooking something. But I haven't found a solution from anything Google has yielded during an hour long search. Maybe I'm using the wrong keywords!

Module.parent called in your module lets you access to the exports of the file it was called from.
You can put the function below in your main.js and you can call module.parent.filename() in your module.
module.exports.filename = function () {
return __filename;
}

Related

Cannot find module XYZ

I know this problem has been submitted endless times but even after browsing through X questions and possible solutions this error still remains.
I have a file called tournament.js in the directory modules. tournament.js requires model.js which resides in the exact same directory. The structure is the following:
app/
modules/
model.js
tournament.js
tournament.js looks like:
const Model = require('./model');
class Tournament extends Model {
constructor() {
super();
}
static create() {
}
}
Even WebStorm says the path in require() is correct but my console still says: Uncaught Error: Cannot find module './model'
What am I missing?
Edit: I'm using Node v6.4.0 and Electron v1.4.15
Okay #adelphus gave me the correct hint. I outputted the path with console.log(__dirname) and it was not what I expected: Yes, I have been in the wrong path, because I thought the relative path require() takes is the one relative to the file I am currently working in (which was the tournament.js) and this is not the case.
Instead require() takes the path relative from the app root which in this case was ./app/models/model.js

How to require a file relative to requirer?

I'm developing a library where I would like to load one or more files relative to the requirer. To better illustrate this:
// ~/app.js
import { horn } from 'unicorn'
horn.load()
// ~/node_modules/unicorn/horn.js
export default {
load() {
require('./user.config.js') // Here I would like to load the user config
// relative to "~/app.js"
}
}
I tried inspecting the global require and its parent property but it only give me a filename without more context.
Here's what you have available:
module.parent
This is the module handle of the first module to load this module. Because module handles are cached, this will only reflect the first module that loaded you.
module.filename
This is the fully qualified filename to a module. So, if you want the fully qualified filename of the parent module, you could use this:
module.parent.filename
If you just want the path of the parent module so that you could load something from that directory, then you can split off the path from the filename to get just the path using the path module.
path.dirname(module.parent.filename)
If you want to load a file from that directory, you could do this:
let fileToLoad = path.join(path.dirname(module.parent.filename), "user.config.js");
let config = require(fileToLoad);
You will have to remember the caveat above that module.parent only returns the very first module to load you because after that the module is cached and just the original module handle is returned (it is not reloaded).

Meteor.js - requiring files

I am struggling to find the Meteor API call analogous to this CommonJS require call:
var file = require('file.js');
http://docs.meteor.com/#/full/structuringyourapp
so to my dear Meteor folks: why is this so hard to find? Can someone please point me in the direction of this info?
Meteor is a bit different this way. Any file that is a .js file is automatically included in the project and concatenated into a big js file.
The way you can picture it is every single js file in your project is just one file.
Variables in other files are enclaved if they are defined using the var keyword, and are global if they're defined in the way foo = "bar".
There section at http://docs.meteor.com/#/full/structuringyourapp explains how the files are loaded & in what order:
For example if you place your files in a folder called server then all those will only run on the server.
To do what you're trying to do you can have
file.js
Foo = function() {
return "bar"
}
//usually exports = Foo()
Then in your other files, instead of var Foo = require("file.js"); Foo(), you can just have Foo() without the require or exports stuff.

Not modifying a loaded node module

In my Node app, have a config file like this:
module.exports = {
BUILD_DIR: '/some.path',
OTHER_CONFIG: 42,
// ...
};
I also have some tests doing things like
var appConfig = require('./path/to/appConfig');
appConfig.BUILD_DIR = 'tmp/some/path';
// and stuff done with appConfig
To my big surprise doing this apparently modifies the state of the module. My next test that requires it will have BUILD_DIR set to 'tmp/some/path'. I did not realize modules had this kind of state across requires. How do I get rid of this effect in my test? Also, how can I prevent people from modifying the state of this module? If someone includes it, they should always get what it defines, and not possibly something some other code wrote to it.
The reason why is explained here:
Modules are cached after the first time they are loaded. This means
(among other things) that every call to require('foo') will get
exactly the same object returned, if it would resolve to the same
file.
(emphasis mine)
So the object that you're exporting is cached and shared among the code that uses it.
If that's not what you want, you could export a function instead:
module.exports = function() {
return {
BUILD_DIR: '/some.path',
OTHER_CONFIG: 42,
// ...
};
};
And require it like so:
var appConfig = require('./path/to/appConfig')();
Assuming your module is called 'Config', and you originally:
var Config=require('Config');
you could:
delete require.cache[require.resolve('Config')];
which will remove the module from require's cache, causing it to be loaded afresh when you next 'require' it.
Gist: https://gist.github.com/raisch/6786930

Nodejs importing multiple classes with modules.export from multiple source files

I have a directory with multiple js source files that is imported on client side webpage. I am also needing to import all of those sources files into server side node js app.
I have used the following approach so far
if( 'undefined' != typeof global ) {
module.exports = global.Class= Class;
}
The code is appended to the end of the source file
However I need to avoid editing the source files. Is there a good approach of how to import all of the classes contained the source folders? Instead of just running through the source files and having a modules.exports for each class? Also is there a way to give a directory to the require() call and have it import all the contained source files?
By exporting the objects into the global namespace you are kind of going against best standards in Javascript. The point in the module.exports is so that you can use requireJS to import the object that you need, rather than have every object available to you. So I'm afraid the answer is no, the require call only accepts single module references (due to the return value of the function assigning the object to a variable).
The 'good' approach would be to include a single file on the client that holds your main cilent code that references the modules/objects it needs to continue working. The source files will then be included as and when they are needed.
If you could modify the client side files, you could use this pattern: http://caolanmcmahon.com/posts/writing_for_node_and_the_browser/
file: tool.js
(function(exports) {
exports.Hello = function(name) {
console.log('Hello %s', name);
}
})(exports || window);
file index.js
require('./tool').Hello('username');

Resources