Determine project root from a running node.js application
Asked Answered
H

34

501

Is there a different way, other than process.cwd(), to get the pathname of the current project's root-directory. Does Node implement something like ruby's property, Rails.root,. I'm looking for something that is constant, and reliable.

Heck answered 22/4, 2012 at 6:39 Comment(0)
H
877

There are many 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:

const { dirname } = require('path');
const appDir = 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. This also won't work when using Node.js ES modules, where require.main is not available.

module.paths

Node publishes all the module search paths to module.paths. We can traverse these and pick the first one that resolves.

async function getAppPath() {
  const { dirname } = require('path');
  const { constants, promises: { access } } = require('fs');
  
  for (let path of module.paths) {
    try {
      await access(path, constants.F_OK);
      return dirname(path);
    } catch (e) {
      // Just move on to next path
    }
  }
}

Pros & Cons

This will sometimes work, but is not reliable when used in a package because it may return the directory that the package is installed in rather than the directory that the application is installed in.

Using a global variable

Node has 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:

const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);

The app-root-path module uses several 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.

Hands answered 10/9, 2013 at 14:22 Comment(22)
this yield's the mocha bin directory for me: /usr/local/lib/node_modules/mocha/bin. What am I missing?Stereoisomerism
@Stereoisomerism in this case, mocha is the entry point of your application. This is just an example of why finding the "project root" is so difficult--it depends so much on the situation and what you mean by "project root."Hands
@Hands I suppose; I was just running a unit test against an app that happened to be started by mocha. I was hoping to get at the project root, whereever it happened to be installed, not the root directory of the program running the project.Stereoisomerism
@Stereoisomerism I completely understand. My point is just that the concept of "project root" is much easier for a human to understand than a computer. If you want a fool-proof method, you need to configure it. Using require.main.filename will work most of the time, but not all of the time.Hands
@Stereoisomerism I doubt you're still following this, but see my latest update—the app-root-path module should help.Hands
Tangentially related: this is an incredibly clever way to organize your Node project so that you don't have to worry about this problem so much: allanhortle.com/2015/02/04/…Hands
@Hands that link is awesome, it works with SailsJS, just creating the node_modules folder inside api/controllers. Then you can simply require it without any path and worksNaamana
I don't know if there was a change in pm2 or a change with Node.js but require.main.filename appears to work with pm2. Don't know about mocha.Niklaus
path.parse(process.mainModule.filename).dirFringe
So i understand using global isnt normally a good thing to do but for defining the root directory or other simple strings wouldnt global.App = {root:__dirname} in the main file do the job that way i can just do App.root anywhere?Chlori
@NoahPassalacqua There's nothing inherently wrong with it—it just makes your code a little more fragile because now you're relying on a specific global to be set. It's become an implicit dependency—something that probably will break some day and may be trickier to debug.Hands
From the root directory of the application I'm quite a fan of global.__root = path.resolve(__dirname) as it conforms to the same double underscore and makes it easy to identify and search for everywhere else.Novelia
Why do you use path.resolve here path.resolve(__dirname);. How is it different from __dirname ?Ileenileitis
@Ileenileitis that's a good point. There really shouldn't be a difference. In some cases, like when using webpack to compile a node library for the web, __dirname may not be an absolute path—but that shouldn't really matter here.Hands
"start": "NODE_PATH=. node app.js" results in the literal . being returned inside the app for me. I had to use: NODE_PATH=$PWD to get the actual path in process.env.NODE_PATHChine
Does anyone have a reliable solution that will work when hosted to Heroku and or AWS beanstalk? The npm scripts NODE_PATH= is great but only works for localhostKyle
Similar to the global variable solution I prefer setting an environmental variable: process.env.NODE_ROOT = path.resolve(__dirname); works the same, but doesn't clutter the code. Perhaps you can include it.Quadrennium
For the time being, Unfortunately WebStorm IDE cannot detect path.join(global.appRoot, str) if str is typo, as well as not showing path suggestionBaton
Since v11.14.0 there is also a handy require.main.path which seems to work the same as path.dirname(require.main.filename).Improvement
The node_modules/ directory is always located on the root directory of the project. I've seen somewhere another solution which would recursively cd .. until it found the dir node_modules/, hence the app root directory. Can you comment on that solution?Amphictyony
@João Pimentel Ferreira there are lots of edge cases where the node_modules directory isn't in the root, so that's not safe—especially in a package where you don't know exactly how it'll be installed.Hands
What about the file package.json ? Is not always at the root? In which edge cases is it not?Amphictyony
B
95

__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.

Bligh answered 7/6, 2013 at 15:45 Comment(2)
If used with caution, this could work pretty well. But it would give different results when doing bin/server.js vs cd bin && server.js. (assuming these js files are marked being executable)Tricot
Using process.cwd() has worked like a charm for me, even when running mocha tests. Thank you!Scapula
T
60

Simple:

require('path').resolve('./')
Teethe answered 14/6, 2020 at 20:51 Comment(2)
"If, after processing all given path segments, an absolute path has not yet been generated, the current working directory is used.". This is just a roundabout way of doing process.cwd().Acariasis
This does not work when running the node application from outside the root folder!Obellia
E
45

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

Elite answered 26/5, 2015 at 18:14 Comment(4)
This works great on (most) unix systems. As soon as you want your npm module/app to work on Windows, PWD is undefined and this fails.Ossified
process.cwd()Spring
@MuhammadUmer why would process.cwd() always be the same as project root?Elite
if you call it in root file then it'd beSpring
M
26

As simple as adding this line to your module in the root, usually it is app.js or app.ts.

global.__basedir = __dirname;

Then _basedir will be accessible to all your modules.

Note: For typescript implementation, follow the above step and then you will be able to use the root directory path using global.__basedir

Mercier answered 15/12, 2018 at 12:16 Comment(2)
simple, easy and effectiveSarco
is there any way to typescript type this? otherwise i need to put ts-ignore everywhere __basedir is referenced. a bit like adding extra fields to the window scope...Tervalent
S
21

Try traversing upwards from __dirname until you find a package.json, and decide that's the app main root directory your current file belongs to.

According to Node docs

The package.json file is normally located at the root directory of a Node.js project.

const fs = require('fs')
const path = require('path')

function getAppRootDir () {
  let currentDir = __dirname
  while(!fs.existsSync(path.join(currentDir, 'package.json'))) {
    currentDir = path.join(currentDir, '..')
  }
  return currentDir
}
Suspensoid answered 19/6, 2015 at 16:4 Comment(2)
That's the best solution, indeed! Every NPM project by default has only a single unique package.json always located on the project root directory.Amphictyony
unfortunately this doesn't work, because some app is deployed to .next folder which happens to have a package.json file. However this logic does hold, so i just need to find an unique file to our app.Intercom
S
20

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!

EDIT:

process.mainModule is deprecated as of v14.0.0

Use require.main instead:

require.main.paths[0].split('node_modules')[0].slice(0, -1);

Scrofula answered 14/5, 2017 at 6:8 Comment(4)
process.mainModule deprectaed since: v14.0.0 - use require.main.paths[0].split('node_modules')[0].slice(0, -1); instead.Czarra
What happens if you have more than one node_modules folder, as is the case with Electron appsFauver
The node_modules/ directory is always located on the root directory of the project. That's the reason this worksAmphictyony
shows deprecatedXylotomy
U
20

Preamble

This is a very old question, but it seems to hit the nerve in 2020 as much as back in 2012. I've checked all the other answers and could not find the following technique mentioned (it has its own limitations, but the others are not applicable to every situation either):

Git + child process

If you are using Git as your version control system, the problem of determining the project root can be reduced to (which I would consider the proper root of the project - after all, you would want your VCS to have the fullest visibility scope possible):

retrieve repository root path

Since you have to run a CLI command to do that, we need to spawn a child process. Additionally, as project root is highly unlikely to change mid-runtime, we can use the synchronous version of the child_process module at startup.

I found spawnSync() to be the most suitable for the job. As for the actual command to run, git worktree (with a --porcelain option for ease of parsing) is all that is needed to retrieve the absolute path of the root.

In the sample at the end of the answer, I opted to return an array of paths because there might be multiple worktrees (although they are likely to have common paths) just to be sure. Note that as we utilize a CLI command, shell option should be set to true (security shouldn't be an issue as there is no untrusted input).

Approach comparison and fallbacks

Understanding that a situation where VCS can be inaccessible is possible, I've included a couple of fallbacks after analyzing docs and other answers. The proposed solutions boil down to (excluding third-party modules & packages):

Solution Advantage Main Problem
__filename points to module file relative to module
__dirname points to module dir same as __filename
node_modules tree walk nearly guaranteed root complex tree walking if nested
path.resolve(".") root if CWD is root same as process.cwd()
process.argv\[1\] same as __filename same as __filename
process.env.INIT_CWD points to npm run dir requires npm && CLI launch
process.env.PWD points to current dir relative to (is the) launch dir
process.cwd() same as env.PWD process.chdir(path) at runtime
require.main.filename root if === module fails on required modules

From the comparison table above, the following approaches are the most universal:

  • require.main.filename as an easy way to get the root if require.main === module is met
  • node_modules tree walk proposed recently uses another assumption:

if the directory of the module has node_modules dir inside, it is likely to be the root

For the main app, it will get the app root and for a module — its project root.

Fallback 1. Tree walk

My implementation uses a more lax approach by stopping once a target directory is found as for a given module its root is the project root. One can chain the calls or extend it to make the search depth configurable:

/**
 * @summary gets root by walking up node_modules
 * @param {import("fs")} fs
 * @param {import("path")} pt
 */
const getRootFromNodeModules = (fs, pt) =>

    /**
     * @param {string} [startPath]
     * @returns {string[]}
     */
    (startPath = __dirname) => {

        //avoid loop if reached root path
        if (startPath === pt.parse(startPath).root) {
            return [startPath];
        }

        const isRoot = fs.existsSync(pt.join(startPath, "node_modules"));

        if (isRoot) {
            return [startPath];
        }

        return getRootFromNodeModules(fs, pt)(pt.dirname(startPath));
    };

Fallback 2. Main module

The second implementation is trivial:

/**
 * @summary gets app entry point if run directly
 * @param {import("path")} pt
 */
const getAppEntryPoint = (pt) =>

    /**
     * @returns {string[]}
     */
    () => {

        const { main } = require;

        const { filename } = main;

        return main === module ?
            [pt.parse(filename).dir] :
            [];
    };

Implementation

I would suggest using the tree walker as the preferred fallback because it is more versatile:

const { spawnSync } = require("child_process");
const pt = require('path');
const fs = require("fs");

/**
 * @summary returns worktree root path(s)
 * @param {function : string[] } [fallback]
 * @returns {string[]}
 */
const getProjectRoot = (fallback) => {

    const { error, stdout } = spawnSync(
        `git worktree list --porcelain`,
        {
            encoding: "utf8",
            shell: true
        }
    );

    if (!stdout) {
        console.warn(`Could not use GIT to find root:\n\n${error}`);
        return fallback ? fallback() : [];
    }

    return stdout
        .split("\n")
        .map(line => {
            const [key, value] = line.split(/\s+/) || [];
            return key === "worktree" ? value : "";
        })
        .filter(Boolean);
};

Disadvantages

The most obvious one is having Git installed and initialized which might be undesirable/implausible (side note: having Git installed on production servers is not uncommon, nor is it unsafe). Can be mediated by fallbacks as described above.

Umbrageous answered 26/5, 2020 at 1:3 Comment(0)
C
16

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');
Cronus answered 18/4, 2014 at 13:10 Comment(0)
R
10

There is an INIT_CWD property on process.env. This is what I'm currently working with in my project.

const {INIT_CWD} = process.env; // process.env.INIT_CWD 
const paths = require(`${INIT_CWD}/config/paths`);

Good Luck...

Regressive answered 18/10, 2019 at 4:25 Comment(3)
Worked like a charm for a package that manipulate the project it is being called from as a postinstall step. I have however not yet tested it in another layer of dependency, where a project uses a dependency that uses my package.Deloris
@JamesDev, INIT_CWD resolves to the directory from which the npm-script was exectued.Regressive
@Aakash, require doesn't work with ESM, but I succeeded to get a root just with process.env.INIT_CWD.Malik
E
6

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.

Eldredge answered 10/8, 2015 at 10:51 Comment(0)
E
6

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
Edifice answered 5/2, 2017 at 11:17 Comment(1)
__dirname is not defined in ES modules ("type": "module" in the package.json).Mate
B
4

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...

Boneblack answered 5/10, 2018 at 8:11 Comment(0)
M
4

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

Maureen answered 30/11, 2018 at 11:39 Comment(0)
T
3

process.mainModule is deprecated since v 14.0.0. When referring to the answer, please use require.main, the rest still holds.

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.

Tautologize answered 18/3, 2018 at 0:59 Comment(0)
J
2

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.
Jamin answered 28/5, 2016 at 6:58 Comment(0)
J
2

if you want to determine project root from a running node.js application you can simply just too.

process.mainModule.path
Jasmine answered 11/11, 2019 at 16:34 Comment(1)
[tsserver 6385] 'mainModule' is deprecatedBedel
C
1

It work for me

process.env.PWD
Chantry answered 24/1, 2020 at 5:50 Comment(0)
V
1

This will step down the directory tree until it contains a node_modules directory, which usually indicates your project root:

const fs = require('fs')
const path = require('path')

function getProjectRoot(currentDir = __dirname.split(path.sep)) {
  if (!currentDir.length) {
    throw Error('Could not find project root.')
  }
  const nodeModulesPath = currentDir.concat(['node_modules']).join(path.sep)
  if (fs.existsSync(nodeModulesPath) && !currentDir.includes('node_modules')) {
    return currentDir.join(path.sep)
  }
  return this.getProjectRoot(currentDir.slice(0, -1))
}

It also makes sure that there is no node_modules in the returned path, as that means that it is contained in a nested package install.

Vinia answered 25/4, 2020 at 17:59 Comment(0)
P
0

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'));
Photographer answered 1/3, 2015 at 4:59 Comment(0)
A
0

I use this.

For my module named mymodule

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')

Ashton answered 2/12, 2016 at 15:8 Comment(0)
R
0

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.

  1. Install the package: npm install sexy-require --save
  2. Include require('sexy-require') once on the top of your main application file.

    require('sexy-require');
    const routers = require('/routers');
    const api = require('$api');
    ...
    
  3. 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
    
Radiator answered 12/1, 2018 at 17:50 Comment(2)
Seems decent, too bad it had such a ridiculous name.Nuli
@Nuli well... I had to find a better nameRadiator
J
0

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.

Jedidiah answered 24/6, 2018 at 10:15 Comment(0)
V
0

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 || '';
    }
}; 
Verduzco answered 27/9, 2018 at 3:7 Comment(0)
D
0

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' });
Deepfreeze answered 20/1, 2019 at 8:5 Comment(0)
B
0

This will do:

path.join(...process.argv[1].split(/\/|\\/).slice(0, -1))
Bargain answered 1/10, 2019 at 21:13 Comment(0)
T
0
path.dirname(process.mainModule.filename);
Thoughtout answered 2/12, 2019 at 13:57 Comment(1)
process.mainModule was deprecated in favor of require.main. (and if you're using ES6 modules, neither of these will work...)Paulinapauline
E
0

In modern versions of npm, you can add an entry to exports, to use as a shorthand. Note that if you want to be able to reference both the root itself and files within that root, you'll need both ./ and ./* respectively:

package.json:

{
  "imports": {
    "#root": "./",
    "#root/*": "./*",
    ...
  },
  ...
}

./index.js:

import {namedExport} from '#root/file.js'

./file.js:

export const namedExport = {
  hi: "world",
};

Then:

$ node --experimental-specifier-resolution=node index.js

You could extend this further with a constants.js file, where you may use one of the methods in the above answers, or input an absolute path, should you require the path itself

Exemplum answered 11/1, 2022 at 19:19 Comment(0)
C
0

You can also use git rev-parse --show-toplevel Assuming you are working on a git repository

Cuesta answered 31/5, 2022 at 8:36 Comment(0)
C
0

A very simple and reliable solution would be to cd .. recursively searching for package.json, considering that this file is always on the project root directory.

const fs = require('fs')
const path = require('path')

function getAppRootDir () {
  let currentDir = __dirname
  while(!fs.existsSync(path.join(currentDir, 'package.json'))) {
    currentDir = path.join(currentDir, '..')
  }
  return currentDir
}
Conger answered 22/8, 2022 at 21:4 Comment(0)
C
0
const __root = `${__dirname.substring(0, __dirname.lastIndexOf('projectName'))}projectName`

`

Cheatham answered 7/9, 2022 at 5:32 Comment(0)
B
-1

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)

Brachiate answered 28/6, 2016 at 18:38 Comment(0)
T
-1

Just use:

 path.resolve("./") ... output is your project root directory
Toplofty answered 10/10, 2018 at 9:34 Comment(2)
this works great! path.resolve(".") works as wellSleepwalk
That only gives the current directory, which may not be the root directory.Jameyjami
H
-5

__dirname will give you the root directory, as long as you're in a file that's in the root directory.

// ProjectDirectory.js (this file is in the project's root directory because you are putting it there).
module.exports = {

    root() {
        return __dirname;
    }
}

In some other file:

const ProjectDirectory = require('path/to/ProjectDirectory');
console.log(`Project root directory is ${ProjectDirectory.root}`);
Harrietteharrigan answered 25/3, 2019 at 17:45 Comment(4)
So it doesn't give you the root directory.Sundog
What? It gives you the root directory. Try it. Are you not able to access JS files in your project's root directory for some reason? As long as you are, create a JS object and have it check __dirname. Guaranteed it will work.Harrietteharrigan
@AndrewKoster __dirname does not give you root directory by design, because it provides you directory name of the current script. Moreover, It could be changed from script to script. If you have it the same as docroot, it just coincidence no more, and narrates only about one fact - you have app.js stored inside your docroot.Bufordbug
It's not a coincidence that this ProjectDirectory.js is at the root directory, if you put it there on purpose. It's a design feature of the working solution that I've posted.Harrietteharrigan

© 2022 - 2024 — McMap. All rights reserved.