inxilpro / node-app-root-path

Determine the root path to your project
MIT License
604 stars 29 forks source link

Incorrect path when used within both project and its dependency on npm v3 #17

Closed doublemarked closed 8 years ago

doublemarked commented 8 years ago

Hello!

I have been using app-root-path for numerous projects and have found it reliable and helpful. However, my frequent use seems to now be catching up to me.

I have two projects - a module I have published and a web app - both of which are using app-root-path. The app loads first, requires app-root-path, and then later loads the module which again requires app-root-path. Because npm 3 is now deduping modules there is only one installation of app-root-path (inside my-web-app/node_modules), and these two projects then share a single handle. Thus, my module that the app depends on is erroneously determining that its app-root-path is within the web app, not within its module folder.

If the web app were not using app-root-path this would presumably not be a problem because app-root-path would initialize only when the module loads it.

This seems like a notable problem with app-root-path, unearthed by the deduping behavior of npm v3. Any ideas on a solution? The module's design seems to be such that it's caching paths and I am aware of no way to force npm to install it locally (no dedupe).

inxilpro commented 8 years ago

Can you give me a better idea of your directory structure? Like this?

app/
    node_modules/
    webapp/
        node_modules/

Or, even better, can you send me a code sample the demonstrates this behavior?

doublemarked commented 8 years ago

My directory structure looks like this,

   my-web-app/
      node_modules/
         app-root-path/
         my-module/

Normally, if I were to clone and npm install inside my-module, the directory structure would look like,

   my-module/
      node_modules/
         app-root-path/

However, npm v3 sees that the same version of app-root-path is used both by my-web-app and my-module and so it moves it up to flatten the dependency hierarchy.

I can put together a code sample!

doublemarked commented 8 years ago

Here you go: https://github.com/doublemarked/app-root-issue-17 https://github.com/doublemarked/app-root-issue-17-module

To reproduce,

  1. Clone the module by itself, npm install then node index.js
  2. Then, clone the base project separately (which depends on the module), npm install and node index.js

Output is like:

Scallop:app-root-issue-17-module heath$ node index.js
MODULE APPROOT: /Users/heath/Projects/app-root-issue-17-module
Scallop:app-root-issue-17 heath$ node index.js 
BASE APPROOT:/Users/heath/Projects/app-root-issue-17
MODULE APPROOT: /Users/heath/Projects/app-root-issue-17
MYMOD: { appRootPath: '/Users/heath/Projects/app-root-issue-17' }
inxilpro commented 8 years ago

Oh, I inderstand. Yeah--this module isn't meant to solve that problem. app-root-path is meant to find the app's root path, regardless of the directory structure, so what you're seeing is exactly the expected behavior.

I'll try to post a code sample later tonight that would do what you're trying to do.

inxilpro commented 8 years ago

Here's a code sample that can get you the path to the current module, no matter where it's called:

function moduleDirectory(dir, pathSeparator) {
  var sep = pathSeparator || '/';
  var search = 'node_modules' + sep;
  var moduleIndex = dir.lastIndexOf(search);
  var sepIndex = dir.indexOf(sep, moduleIndex + search.length);

  if (-1 === sepIndex) {
    return dir;
  }

  return dir.substring(0, sepIndex);
}

See this JSBin for a demo: http://jsbin.com/qazukeluve/1/edit?js,console