How to get working directory in node-webkit - working-directory

I've got a simple program that can be run from command line.
This program is for live preview of markdown files.
When i'm packaging the app with
cat $NW/nw marknow.nw > marknow
and running from different location:
./build/marknow ../relative/path/to/file.md
I can't get current working directory.
process.cwd()
is returning /tmp/something???
How can I get working directory in node-webkit? Directory from which ./build/marknow ../relative/path/to/file.md was called.

I think cwd is getting 2 different meanings:
directory where the app lives
directory where the user launch the app from
In shell scripting I can see the 2nd meaning applied, but the node-webkit community
seems to be using the 1st
Correct me if I'm wrong, but I think you are looking for the 2nd: the path where the user was when calling to your app.
After some tests I finally found a way that works for me:
process.env.PWD

Another option you could try if the cwd doesn't seem to work is getting the execution directory with something like this:
var path = require('path');
var execPath = path.dirname( process.execPath );
This should get you the execution directory of the exe. cwd gets the temp directory because of how node-webkit handles opening the files from a temp directory on each run.

As is pointed out in other answers, node-webkit starts up the node process with the wrong 'current working directory' (from a command line perspective anyway).
As is pointed out elsewhere, process.env.PWD in fact contains what we want (when the app is started from the command line). A simple workaround could then be to do the following in your index.html (or some other place that gets executed early):
<script type="text/javascript">
if(process.env.PWD) {
process.chdir(process.env.PWD);
}
</script>
Presto! Now process.cwd() returns the right thing.
Apparently, this trick only really works for apps that are started from the command line - but then again, it is probably only necessary when the app is launched from the command line.
There is a ticket for this issue, but it is old and dusty

If all answer were failed, try this.
Create file "main.js" and copy this code.
// get child_process module.
var childproc = require('child_process');
// start process using child_process
// with current path string
// '__dirname' would be not only path
// of 'main.js' but also one of 'app.zip'
// because 'main.js' and 'app.zip' have same directory
childproc.exec('nw app.zip ' + __dirname);
Add this code which you want to get current path
// get 'nw.gui' module
var gui = require('nw.gui');
// get arguments that we passed
var arr = gui.App.argv;
// nw app.zip __dirname
// ^ argv[0]
alert('current path: [' + arr[0] + ']');
Run "main.js" with node.js
I posted "How to get current directory(current path) using node-webkit".
http://hdnua.tistory.com/16
It gets executing zip file's directory.

Related

node.js child process doesn't work in node webkit

I made a small app with node webkit. Pre-packaging, it works fine. But after I zipped it and added it to Contents/Resources in node-webkit.app I get an error when I run the app. It opens fine, but the task it does involves child processes, and I get this error:
Uncaught node.js Error
Error: spawn ENOENT.
I'm guessing it might be something related to the issue raised in this question: Node-Webkit Child Process Exec
because my child processes are calling pdftk, a separate command line program. Ultimately, I'd love to install pdftk as part of my app - I have not been able to figure out how to do this. I tried including it as one of the things to be zipped with the rest of the app, but that caused the app to crash immediately after launch (it would open a window with the correct title but no contents, which would immediately close).
So, main question is, how do I install pdftk as part of a packaged node-webkit app, so that the app can be launched simply by double clicking the icon rather than using the command line? Thanks for any help.
I am assuming your code in question is executed via the node-main entry point of node-webkit: https://github.com/rogerwang/node-webkit/wiki/Node-main
If any exception happens (there) which is not catched in your application will crash.
Sadly at the moment the breakpad feature for getting crashdumps is not working on OSX: https://github.com/rogerwang/node-webkit/issues/2518
How to prevent Node-Webkit from crashing immediately
Wrap the code in try/catches to prevent the crash and get information why the crash occurs.
try {
the_child_process = child_process.spawn(pathToBin, args);
} catch (err) {
global.console.log( "Error while trying to start child process: " + JSON.stringify(err) );
}
This is a general advice for a situation like you are experiencing to track down the real cause for the issue.
How to include a binary with your node-webkit app
There are a few things involved.
Including the binaries inside your app.nw
This should be self explanatory - but there is one caveat which caused me some trouble:
Make sure the binary is marked as executable via chmod 755. If you are using grunt you might like grunt-chmod.
Now your binaries are part of your app's package and you can execute them by knowing the absolute path.
Resolve the path to the binary at runtime even when packaged. The following piece of code is my solution for selecting the right binary for the current platform assuming your tool is multi platform. Also it assumes your binaries are ordered in a certain folder structure. Alternatively select the right binary in your build process and use always the same path.
var arch = process.arch;
var platform = process.platform;
// this will return the root path of your app-package at runtime
var rootDir = process.cwd();
var isWin = false;
var execPath = rootDir;
// some base path is appended
execPath = path.join(execPath, 'path', 'to', 'bin');
// select folder for current platform
switch (platform) {
case 'darwin':
execPath = path.join(execPath, 'mac');
break;
case 'linux':
execPath = path.join(execPath, 'lin');
break;
case 'win32':
execPath = path.join(execPath, 'win');
isWin = true;
break;
default:
global.console.log("unsupported platform: " + platform);
return null;
}
// select folder for current processor architecture
switch (arch) {
case 'ia32':
execPath = path.join(execPath, 'x86');
break;
case 'x64':
execPath = path.join(execPath, 'x64');
break;
default:
global.console.log("unsupported architecture: " + arch);
return null;
}
// add executable filename
execPath = path.join(execPath, 'node');
if (isWin) {
execPath = execPath + ".exe";
}
global.console.log("Path to your binary: " + execPath);
return execPath;
Resolve the paths which are fed to your binary as arguments eventually. This was also a bit confusing because all paths were treated as relative to the app's package root path. My node-main file resides in a folder in my app package so I thought I should reference files relative from there, but this was not the case.
app package root
|--- package.json <- node-webkit package.json
|
|--- client <- here my sources for the frontend reside
|
|--- server
|----|--- node_modules <- server runtime dependencies
|----|--- src <- server source code
|----|----|--- server.js <- this is my node server file to execute via node
|
|--- node-webkit <- node webkit code and dependencies
|----|--- bin <- a directory with my deployed binaries
|----|--- node-main.js <- this is my node main file
To invoke a node binary with my server file the following line led to success:
child_process.spawn(absPathToNodeBin, "server/src/server.js");
This is my experience:
var child_process = nw.require('child_process');
//exec
var exec = child_process.exec;
var ret = exec('cat *');
//spawn
var sp = child_process.spawn;
var sr = sp('cat *');

How to create file on the project that installed your package? [duplicate]

Is there a better way than process.cwd() to determine the root directory of a running node.js process? Something like the equivalent of Rails.root, but for Node.js. I'm looking for something that is as predictable and reliable as possible.
There are several ways to approach this, each with their own pros and cons:
require.main.filename
From http://nodejs.org/api/modules.html:
When a file is run directly from Node, require.main is set to its module. That means that you can determine whether a file has been run directly by testing require.main === module
Because module provides a filename property (normally equivalent to __filename), the entry point of the current application can be obtained by checking require.main.filename.
So if you want the base directory for your app, you can do:
var path = require('path');
var appDir = path.dirname(require.main.filename);
Pros & Cons
This will work great most of the time, but if you're running your app with a launcher like pm2 or running mocha tests, this method will fail.
global.X
Node has a a global namespace object called global — anything that you attach to this object will be available everywhere in your app. So, in your index.js (or app.js or whatever your main app file is named), you can just define a global variable:
// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);
// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');
Pros & Cons
Works consistently but you have to rely on a global variable, which means that you can't easily reuse components/etc.
process.cwd()
This returns the current working directory. Not reliable at all, as it's entirely dependent on what directory the process was launched from:
$ cd /home/demo/
$ mkdir subdir
$ echo "console.log(process.cwd());" > subdir/demo.js
$ node subdir/demo.js
/home/demo
$ cd subdir
$ node demo.js
/home/demo/subdir
app-root-path
To address this issue, I've created a node module called app-root-path. Usage is simple:
var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');
The app-root-path module uses several different techniques to determine the root path of the app, taking into account globally installed modules (for example, if your app is running in /var/www/ but the module is installed in ~/.nvm/v0.x.x/lib/node/). It won't work 100% of the time, but it's going to work in most common scenarios.
Pros & Cons
Works without configuration in most circumstances. Also provides some nice additional convenience methods (see project page). The biggest con is that it won't work if:
You're using a launcher, like pm2
AND, the module isn't installed inside your app's node_modules directory (for example, if you installed it globally)
You can get around this by either setting a APP_ROOT_PATH environmental variable, or by calling .setPath() on the module, but in that case, you're probably better off using the global method.
NODE_PATH environmental variable
If you're looking for a way to determine the root path of the current app, one of the above solutions is likely to work best for you. If, on the other hand, you're trying to solve the problem of loading app modules reliably, I highly recommend looking into the NODE_PATH environmental variable.
Node's Modules system looks for modules in a variety of locations. One of these locations is wherever process.env.NODE_PATH points. If you set this environmental variable, then you can require modules with the standard module loader without any other changes.
For example, if you set NODE_PATH to /var/www/lib, the the following would work just fine:
require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js
A great way to do this is using npm:
"scripts": {
"start": "NODE_PATH=. node app.js"
}
Now you can start your app with npm start and you're golden. I combine this with my enforce-node-path module, which prevents accidentally loading the app without NODE_PATH set. For even more control over enforcing environmental variables, see checkenv.
One gotcha: NODE_PATH must be set outside of the node app. You cannot do something like process.env.NODE_PATH = path.resolve(__dirname) because the module loader caches the list of directories it will search before your app runs.
[added 4/6/16] Another really promising module that attempts to solve this problem is wavy.
__dirname isn't a global; it's local to the current module so each file has its own local, different value.
If you want the root directory of the running process, you probably do want to use process.cwd().
If you want predictability and reliability, then you probably need to make it a requirement of your application that a certain environment variable is set. Your app looks for MY_APP_HOME (Or whatever) and if it's there, and the application exists in that directory then all is well. If it is undefined or the directory doesn't contain your application then it should exit with an error prompting the user to create the variable. It could be set as a part of an install process.
You can read environment variables in node with something like process.env.MY_ENV_VARIABLE.
1- create a file in the project root call it settings.js
2- inside this file add this code
module.exports = {
POST_MAX_SIZE : 40 , //MB
UPLOAD_MAX_FILE_SIZE: 40, //MB
PROJECT_DIR : __dirname
};
3- inside node_modules create a new module name it "settings" and inside the module index.js write this code:
module.exports = require("../../settings");
4- and any time you want your project directory just use
var settings = require("settings");
settings.PROJECT_DIR;
in this way you will have all project directories relative to this file ;)
the easiest way to get the global root (assuming you use NPM to run your node.js app 'npm start', etc)
var appRoot = process.env.PWD;
If you want to cross-verify the above
Say you want to cross-check process.env.PWD with the settings of you node.js application. if you want some runtime tests to check the validity of process.env.PWD, you can cross-check it with this code (that I wrote which seems to work well). You can cross-check the name of the last folder in appRoot with the npm_package_name in your package.json file, for example:
var path = require('path');
var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.)
//compare the last directory in the globalRoot path to the name of the project in your package.json file
var folders = globalRoot.split(path.sep);
var packageName = folders[folders.length-1];
var pwd = process.env.PWD;
var npmPackageName = process.env.npm_package_name;
if(packageName !== npmPackageName){
throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.');
}
if(globalRoot !== pwd){
throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.');
}
you can also use this NPM module: require('app-root-path') which works very well for this purpose
I've found this works consistently for me, even when the application is invoked from a sub-folder, as it can be with some test frameworks, like Mocha:
process.mainModule.paths[0].split('node_modules')[0].slice(0, -1);
Why it works:
At runtime node creates a registry of the full paths of all loaded files. The modules are loaded first, and thus at the top of this registry. By selecting the first element of the registry and returning the path before the 'node_modules' directory we are able to determine the root of the application.
It's just one line of code, but for simplicity's sake (my sake), I black boxed it into an NPM module:
https://www.npmjs.com/package/node-root.pddivine
Enjoy!
All these "root dirs" mostly need to resolve some virtual path to a real pile path, so may be you should look at path.resolve?
var path= require('path');
var filePath = path.resolve('our/virtual/path.ext");
Maybe you can try traversing upwards from __filename until you find a package.json, and decide that's the main directory your current file belongs to.
Actually, i find the perhaps trivial solution also to most robust:
you simply place the following file at the root directory of your project: root-path.js which has the following code:
import * as path from 'path'
const projectRootPath = path.resolve(__dirname)
export const rootPath = projectRootPath
A technique that I've found useful when using express is to add the following to app.js before any of your other routes are set
// set rootPath
app.use(function(req, res, next) {
req.rootPath = __dirname;
next();
});
app.use('/myroute', myRoute);
No need to use globals and you have the path of the root directory as a property of the request object.
This works if your app.js is in the root of your project which, by default, it is.
I use this.
For my module named mymodule
var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')
I know this one is already too late.
But we can fetch root URL by two methods
1st method
var path = require('path');
path.dirname(require.main.filename);
2nd method
var path = require('path');
path.dirname(process.mainModule.filename);
Reference Link:- https://gist.github.com/geekiam/e2e3e0325abd9023d3a3
Create a function in app.js
/*Function to get the app root folder*/
var appRootFolder = function(dir,level){
var arr = dir.split('\\');
arr.splice(arr.length - level,level);
var rootFolder = arr.join('\\');
return rootFolder;
}
// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));
At top of main file add:
mainDir = __dirname;
Then use it in any file you need:
console.log('mainDir ' + mainDir);
mainDir is defined globally, if you need it only in current file - use __dirname instead.
main file is usually in root folder of the project and is named like main.js, index.js, gulpfile.js.
Make it sexy 💃🏻.
const users = require('../../../database/users'); // 👎 what you have
// OR
const users = require('$db/users'); // 👍 no matter how deep you are
const products = require('/database/products'); // 👍 alias or pathing from root directory
Three simple steps to solve the issue of ugly path.
Install the package: npm install sexy-require --save
Include require('sexy-require') once on the top of your main application file.
require('sexy-require');
const routers = require('/routers');
const api = require('$api');
...
Optional step. Path configuration can be defined in .paths file on root directory of your project.
$db = /server/database
$api-v1 = /server/api/legacy
$api-v2 = /server/api/v2
process.mainModule.paths
.filter(p => !p.includes('node_modules'))
.shift()
Get all paths in main modules and filter out those with "node_modules",
then get the first of remaining path list. Unexpected behavior will not throw error, just an undefined.
Works well for me, even when calling ie $ mocha.
You can simply add the root directory path in the express app variable and get this path from the app. For this add app.set('rootDirectory', __dirname); in your index.js or app.js file. And use req.app.get('rootDirectory') for getting the root directory path in your code.
Old question, I know, however no question mention to use progress.argv. The argv array includes a full pathname and filename (with or without .js extension) that was used as parameter to be executed by node. Because this also can contain flags, you must filter this.
This is not an example you can directly use (because of using my own framework) but I think it gives you some idea how to do it. I also use a cache method to avoid that calling this function stress the system too much, especially when no extension is specified (and a file exist check is required), for example:
node myfile
or
node myfile.js
That's the reason I cache it, see also code below.
function getRootFilePath()
{
if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
{
var sExt = false;
each( process.argv, function( i, v )
{
// Skip invalid and provided command line options
if( !!v && isValidString( v ) && v[0] !== '-' )
{
sExt = getFileExt( v );
if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
{
var a = uniformPath( v ).split("/");
// Chop off last string, filename
a[a.length-1]='';
// Cache it so we don't have to do it again.
oData.SU_ROOT_FILE_PATH=a.join("/");
// Found, skip loop
return true;
}
}
}, true ); // <-- true is: each in reverse order
}
return oData.SU_ROOT_FILE_PATH || '';
}
};
As simple as add this line to your module in root, usually it is app.js
global.__basedir = __dirname;
Then _basedir will be accessiable to all your modules.
Finding the root path of an electron app could get tricky. Because the root path is different for the main process and renderer under different conditions such as production, development and packaged conditions.
I have written a npm package electron-root-path to capture the root path of an electron app.
$ npm install electron-root-path
or
$ yarn add electron-root-path
// Import ES6 way
import { rootPath } from 'electron-root-path';
// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;
// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });
__dirname will give you the root directory, as long as you're in a file that's in the root directory.
Try path._makeLong('some_filename_on_root.js');
example:
cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');
That will return full path from root of your node application (same position of package.json)
Add this somewhere towards the start of your main app file (e.g. app.js):
global.__basedir = __dirname;
This sets a global variable that will always be equivalent to your app's base dir. Use it just like any other variable:
const yourModule = require(__basedir + '/path/to/module.js');
Simple...
to get current file's pathname:
define in that file:
var get_stack = function() {
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
var err = new Error;
Error.captureStackTrace(err, arguments.callee);
var stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
};
usage in that file:
console.log(get_stack()[0].getFileName());
API:
StackTrace
Just use:
path.resolve("./") ... output is your project root directory

Determine project root from a running node.js application

Is there a better way than process.cwd() to determine the root directory of a running node.js process? Something like the equivalent of Rails.root, but for Node.js. I'm looking for something that is as predictable and reliable as possible.
There are several ways to approach this, each with their own pros and cons:
require.main.filename
From http://nodejs.org/api/modules.html:
When a file is run directly from Node, require.main is set to its module. That means that you can determine whether a file has been run directly by testing require.main === module
Because module provides a filename property (normally equivalent to __filename), the entry point of the current application can be obtained by checking require.main.filename.
So if you want the base directory for your app, you can do:
var path = require('path');
var appDir = path.dirname(require.main.filename);
Pros & Cons
This will work great most of the time, but if you're running your app with a launcher like pm2 or running mocha tests, this method will fail.
global.X
Node has a a global namespace object called global — anything that you attach to this object will be available everywhere in your app. So, in your index.js (or app.js or whatever your main app file is named), you can just define a global variable:
// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);
// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');
Pros & Cons
Works consistently but you have to rely on a global variable, which means that you can't easily reuse components/etc.
process.cwd()
This returns the current working directory. Not reliable at all, as it's entirely dependent on what directory the process was launched from:
$ cd /home/demo/
$ mkdir subdir
$ echo "console.log(process.cwd());" > subdir/demo.js
$ node subdir/demo.js
/home/demo
$ cd subdir
$ node demo.js
/home/demo/subdir
app-root-path
To address this issue, I've created a node module called app-root-path. Usage is simple:
var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');
The app-root-path module uses several different techniques to determine the root path of the app, taking into account globally installed modules (for example, if your app is running in /var/www/ but the module is installed in ~/.nvm/v0.x.x/lib/node/). It won't work 100% of the time, but it's going to work in most common scenarios.
Pros & Cons
Works without configuration in most circumstances. Also provides some nice additional convenience methods (see project page). The biggest con is that it won't work if:
You're using a launcher, like pm2
AND, the module isn't installed inside your app's node_modules directory (for example, if you installed it globally)
You can get around this by either setting a APP_ROOT_PATH environmental variable, or by calling .setPath() on the module, but in that case, you're probably better off using the global method.
NODE_PATH environmental variable
If you're looking for a way to determine the root path of the current app, one of the above solutions is likely to work best for you. If, on the other hand, you're trying to solve the problem of loading app modules reliably, I highly recommend looking into the NODE_PATH environmental variable.
Node's Modules system looks for modules in a variety of locations. One of these locations is wherever process.env.NODE_PATH points. If you set this environmental variable, then you can require modules with the standard module loader without any other changes.
For example, if you set NODE_PATH to /var/www/lib, the the following would work just fine:
require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js
A great way to do this is using npm:
"scripts": {
"start": "NODE_PATH=. node app.js"
}
Now you can start your app with npm start and you're golden. I combine this with my enforce-node-path module, which prevents accidentally loading the app without NODE_PATH set. For even more control over enforcing environmental variables, see checkenv.
One gotcha: NODE_PATH must be set outside of the node app. You cannot do something like process.env.NODE_PATH = path.resolve(__dirname) because the module loader caches the list of directories it will search before your app runs.
[added 4/6/16] Another really promising module that attempts to solve this problem is wavy.
__dirname isn't a global; it's local to the current module so each file has its own local, different value.
If you want the root directory of the running process, you probably do want to use process.cwd().
If you want predictability and reliability, then you probably need to make it a requirement of your application that a certain environment variable is set. Your app looks for MY_APP_HOME (Or whatever) and if it's there, and the application exists in that directory then all is well. If it is undefined or the directory doesn't contain your application then it should exit with an error prompting the user to create the variable. It could be set as a part of an install process.
You can read environment variables in node with something like process.env.MY_ENV_VARIABLE.
1- create a file in the project root call it settings.js
2- inside this file add this code
module.exports = {
POST_MAX_SIZE : 40 , //MB
UPLOAD_MAX_FILE_SIZE: 40, //MB
PROJECT_DIR : __dirname
};
3- inside node_modules create a new module name it "settings" and inside the module index.js write this code:
module.exports = require("../../settings");
4- and any time you want your project directory just use
var settings = require("settings");
settings.PROJECT_DIR;
in this way you will have all project directories relative to this file ;)
the easiest way to get the global root (assuming you use NPM to run your node.js app 'npm start', etc)
var appRoot = process.env.PWD;
If you want to cross-verify the above
Say you want to cross-check process.env.PWD with the settings of you node.js application. if you want some runtime tests to check the validity of process.env.PWD, you can cross-check it with this code (that I wrote which seems to work well). You can cross-check the name of the last folder in appRoot with the npm_package_name in your package.json file, for example:
var path = require('path');
var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.)
//compare the last directory in the globalRoot path to the name of the project in your package.json file
var folders = globalRoot.split(path.sep);
var packageName = folders[folders.length-1];
var pwd = process.env.PWD;
var npmPackageName = process.env.npm_package_name;
if(packageName !== npmPackageName){
throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.');
}
if(globalRoot !== pwd){
throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.');
}
you can also use this NPM module: require('app-root-path') which works very well for this purpose
I've found this works consistently for me, even when the application is invoked from a sub-folder, as it can be with some test frameworks, like Mocha:
process.mainModule.paths[0].split('node_modules')[0].slice(0, -1);
Why it works:
At runtime node creates a registry of the full paths of all loaded files. The modules are loaded first, and thus at the top of this registry. By selecting the first element of the registry and returning the path before the 'node_modules' directory we are able to determine the root of the application.
It's just one line of code, but for simplicity's sake (my sake), I black boxed it into an NPM module:
https://www.npmjs.com/package/node-root.pddivine
Enjoy!
All these "root dirs" mostly need to resolve some virtual path to a real pile path, so may be you should look at path.resolve?
var path= require('path');
var filePath = path.resolve('our/virtual/path.ext");
Maybe you can try traversing upwards from __filename until you find a package.json, and decide that's the main directory your current file belongs to.
Actually, i find the perhaps trivial solution also to most robust:
you simply place the following file at the root directory of your project: root-path.js which has the following code:
import * as path from 'path'
const projectRootPath = path.resolve(__dirname)
export const rootPath = projectRootPath
A technique that I've found useful when using express is to add the following to app.js before any of your other routes are set
// set rootPath
app.use(function(req, res, next) {
req.rootPath = __dirname;
next();
});
app.use('/myroute', myRoute);
No need to use globals and you have the path of the root directory as a property of the request object.
This works if your app.js is in the root of your project which, by default, it is.
I use this.
For my module named mymodule
var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')
I know this one is already too late.
But we can fetch root URL by two methods
1st method
var path = require('path');
path.dirname(require.main.filename);
2nd method
var path = require('path');
path.dirname(process.mainModule.filename);
Reference Link:- https://gist.github.com/geekiam/e2e3e0325abd9023d3a3
Create a function in app.js
/*Function to get the app root folder*/
var appRootFolder = function(dir,level){
var arr = dir.split('\\');
arr.splice(arr.length - level,level);
var rootFolder = arr.join('\\');
return rootFolder;
}
// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));
At top of main file add:
mainDir = __dirname;
Then use it in any file you need:
console.log('mainDir ' + mainDir);
mainDir is defined globally, if you need it only in current file - use __dirname instead.
main file is usually in root folder of the project and is named like main.js, index.js, gulpfile.js.
Make it sexy 💃🏻.
const users = require('../../../database/users'); // 👎 what you have
// OR
const users = require('$db/users'); // 👍 no matter how deep you are
const products = require('/database/products'); // 👍 alias or pathing from root directory
Three simple steps to solve the issue of ugly path.
Install the package: npm install sexy-require --save
Include require('sexy-require') once on the top of your main application file.
require('sexy-require');
const routers = require('/routers');
const api = require('$api');
...
Optional step. Path configuration can be defined in .paths file on root directory of your project.
$db = /server/database
$api-v1 = /server/api/legacy
$api-v2 = /server/api/v2
process.mainModule.paths
.filter(p => !p.includes('node_modules'))
.shift()
Get all paths in main modules and filter out those with "node_modules",
then get the first of remaining path list. Unexpected behavior will not throw error, just an undefined.
Works well for me, even when calling ie $ mocha.
You can simply add the root directory path in the express app variable and get this path from the app. For this add app.set('rootDirectory', __dirname); in your index.js or app.js file. And use req.app.get('rootDirectory') for getting the root directory path in your code.
Old question, I know, however no question mention to use progress.argv. The argv array includes a full pathname and filename (with or without .js extension) that was used as parameter to be executed by node. Because this also can contain flags, you must filter this.
This is not an example you can directly use (because of using my own framework) but I think it gives you some idea how to do it. I also use a cache method to avoid that calling this function stress the system too much, especially when no extension is specified (and a file exist check is required), for example:
node myfile
or
node myfile.js
That's the reason I cache it, see also code below.
function getRootFilePath()
{
if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
{
var sExt = false;
each( process.argv, function( i, v )
{
// Skip invalid and provided command line options
if( !!v && isValidString( v ) && v[0] !== '-' )
{
sExt = getFileExt( v );
if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
{
var a = uniformPath( v ).split("/");
// Chop off last string, filename
a[a.length-1]='';
// Cache it so we don't have to do it again.
oData.SU_ROOT_FILE_PATH=a.join("/");
// Found, skip loop
return true;
}
}
}, true ); // <-- true is: each in reverse order
}
return oData.SU_ROOT_FILE_PATH || '';
}
};
As simple as add this line to your module in root, usually it is app.js
global.__basedir = __dirname;
Then _basedir will be accessiable to all your modules.
Finding the root path of an electron app could get tricky. Because the root path is different for the main process and renderer under different conditions such as production, development and packaged conditions.
I have written a npm package electron-root-path to capture the root path of an electron app.
$ npm install electron-root-path
or
$ yarn add electron-root-path
// Import ES6 way
import { rootPath } from 'electron-root-path';
// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;
// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });
__dirname will give you the root directory, as long as you're in a file that's in the root directory.
Try path._makeLong('some_filename_on_root.js');
example:
cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');
That will return full path from root of your node application (same position of package.json)
Add this somewhere towards the start of your main app file (e.g. app.js):
global.__basedir = __dirname;
This sets a global variable that will always be equivalent to your app's base dir. Use it just like any other variable:
const yourModule = require(__basedir + '/path/to/module.js');
Simple...
to get current file's pathname:
define in that file:
var get_stack = function() {
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
var err = new Error;
Error.captureStackTrace(err, arguments.callee);
var stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
};
usage in that file:
console.log(get_stack()[0].getFileName());
API:
StackTrace
Just use:
path.resolve("./") ... output is your project root directory

Find absolute base path of the project directory

Until now we could get the absolute path of a file to open later as readStream with this code snippet:
var base = path.resolve('.');
var file = base + '/data/test.csv';
fs.createReadStream(file)
Since Meteor 0.6.5 the base path is pointing to .meteor/local/build/programs/...
There is also the Assets API, which but can not give us back a path but only the read document. We but need a stream to process some bigger data files?
Another way to find your project's root directory now is this:
var base = process.env.PWD
Note that this is not the same as process.cwd(). Instead it is the directory where you ran the meteor command, which is typically what you are looking for. Note also that this probably won't be very helpful when running your app from a deployed bundle.
I ran into the same predicament when I updated to 0.6.5.
What I'm currently doing is getting the path like this:
var meteor_root = Npm.require('fs').realpathSync( process.cwd() + '/../' );
This returns on dev mode:
/my/application/.meteor/local/build/programs
and on bundled mode:
/my/application/build/app/programs
So from here I'm getting to my application's "root" path like so:
var application_root = Npm.require('fs').realpathSync( meteor_root + '/../' );
// if running on dev mode
if( Npm.require('path').basename( Npm.require('fs').realpathSync( meteor_root + '/../../../' ) ) == '.meteor' ){
application_root = Npm.require('fs').realpathSync( meteor_root + '/../../../../' );
}
The only case in which this would fail is if you happen to name your application's folder ".meteor" but that's an edge case.
Relative to that you can access whatever else you need to.
Additionally, you can also get direct access to to the assets folder that the meteor bundler creates:
var assets_folder = meteor_root + '/server/assets/' + Npm.require('path').basename( application_root );
This is likely to be temporary as I expect better file/path interaction APIs to be added eventually..
Hope that helps
Hey you do not need to hardcode like the above answers... take a look to This package
After install it you can access the root path of your meteor just wih Meteor.rootPath
Since version 1.3, the documented function
Assets.absoluteFilePath(assetPath)
seems to be the best way to get the project path reliably.
Meteor Github
For Meteor 0.8.3,
__meteor_bootstrap__.serverDir gives out the working directory, when run in server mode.
example
if (Meteor.isServer) {
console.log(__meteor_bootstrap__.serverDir);
}
As of Meteor 1.2.1, this works for me:
var absoluteBasePath = path.resolve('../../../../../.');
The same result using split:
var absoluteBasePath = path.resolve('.').split(path.sep + '.meteor')[0];
Using process.cwd():
var absoluteBasePath = path.resolve(process.cwd(), '../../../../../');
var absoluteBasePath = path.resolve(process.cwd()).split(path.sep + '.meteor')[0];

How do I get the path to the current script with Node.js?

How would I get the path to the script in Node.js?
I know there's process.cwd, but that only refers to the directory where the script was called, not of the script itself. For instance, say I'm in /home/kyle/ and I run the following command:
node /home/kyle/some/dir/file.js
If I call process.cwd(), I get /home/kyle/, not /home/kyle/some/dir/. Is there a way to get that directory?
I found it after looking through the documentation again. What I was looking for were the __filename and __dirname module-level variables.
__filename is the file name of the current module. This is the resolved absolute path of the current module file. (ex:/home/kyle/some/dir/file.js)
__dirname is the directory name of the current module. (ex:/home/kyle/some/dir)
So basically you can do this:
fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);
Use resolve() instead of concatenating with '/' or '\' else you will run into cross-platform issues.
Note: __dirname is the local path of the module or included script. If you are writing a plugin which needs to know the path of the main script it is:
require.main.filename
or, to just get the folder name:
require('path').dirname(require.main.filename)
This command returns the current directory:
var currentPath = process.cwd();
For example, to use the path to read the file:
var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
if(err)
console.log(err)
else
console.log(data.toString());
});
Use __dirname!!
__dirname
The directory name of the current module. This the same as the path.dirname() of the __filename.
Example: running node example.js from /Users/mjr
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
https://nodejs.org/api/modules.html#modules_dirname
For ESModules you would want to use:
import.meta.url
When it comes to the main script it's as simple as:
process.argv[1]
From the Node.js documentation:
process.argv
An array containing the command line arguments. The first element will be 'node', the second element will be the path to the JavaScript file. The next elements will be any additional command line arguments.
If you need to know the path of a module file then use __filename.
var settings =
JSON.parse(
require('fs').readFileSync(
require('path').resolve(
__dirname,
'settings.json'),
'utf8'));
Every Node.js program has some global variables in its environment, which represents some information about your process and one of it is __dirname.
Node.js 10 supports ECMAScript modules, where __dirname and __filename are no longer available.
Then to get the path to the current ES module one has to use:
const __filename = new URL(import.meta.url).pathname;
And for the directory containing the current module:
import path from 'path';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
You can use process.env.PWD to get the current app folder path.
I know this is pretty old, and the original question I was responding to is marked as duplicate and directed here, but I ran into an issue trying to get jasmine-reporters to work and didn't like the idea that I had to downgrade in order for it to work. I found out that jasmine-reporters wasn't resolving the savePath correctly and was actually putting the reports folder output in jasmine-reporters directory instead of the root directory of where I ran gulp. In order to make this work correctly I ended up using process.env.INIT_CWD to get the initial Current Working Directory which should be the directory where you ran gulp. Hope this helps someone.
var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
savePath: process.env.INIT_CWD + '/report/e2e/',
consolidateAll: true,
captureStdout: true
});
If you are using pkg to package your app, you'll find useful this expression:
appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
process.pkg tells if the app has been packaged by pkg.
process.execPath holds the full path of the executable, which is /usr/bin/node or similar for direct invocations of scripts (node test.js), or the packaged app.
require.main.filename holds the full path of the main script, but it's empty when Node runs in interactive mode.
__dirname holds the full path of the current script, so I'm not using it (although it may be what OP asks; then better use appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0])); noting that in interactive mode __dirname is empty.
For interactive mode, use either process.argv[0] to get the path to the Node executable or process.cwd() to get the current directory.
Use the basename method of the path module:
var path = require('path');
var filename = path.basename(__filename);
console.log(filename);
Here is the documentation the above example is taken from.
As Dan pointed out, Node is working on ECMAScript modules with the "--experimental-modules" flag. Node 12 still supports __dirname and __filename as above.
If you are using the --experimental-modules flag, there is an alternative approach.
The alternative is to get the path to the current ES module:
const __filename = new URL(import.meta.url).pathname;
And for the directory containing the current module:
import path from 'path';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
If you want something more like $0 in a shell script, try this:
var path = require('path');
var command = getCurrentScriptPath();
console.log(`Usage: ${command} <foo> <bar>`);
function getCurrentScriptPath () {
// Relative path from current working directory to the location of this script
var pathToScript = path.relative(process.cwd(), __filename);
// Check if current working dir is the same as the script
if (process.cwd() === __dirname) {
// E.g. "./foobar.js"
return '.' + path.sep + pathToScript;
} else {
// E.g. "foo/bar/baz.js"
return pathToScript;
}
}

Resources