node-optional icon indicating copy to clipboard operation
node-optional copied to clipboard

Doesn't always work with relative paths

Open kflorence opened this issue 10 years ago • 6 comments

If I'm in /home/kflorence/dev/project/foo/bar and I require: optional("../baz/qux") it will fail because it's trying to look up /home/kflorence/dev/project/baz/qux instead of /home/kflorence/dev/project/foo/baz/qux

kflorence avatar Aug 06 '14 17:08 kflorence

Is /home/kflorence/dev/project/foo/bar a file or a dir? I'm assuming it's a directory from the question.

In what directory is the main script located? Is it also in /home/kflorence/dev/project/foo/bar or is it in /home/kflorence/dev/project/foo ?

tony-o avatar Aug 14 '14 18:08 tony-o

Sorry for the ambiguous example, let me try to state it more clearly: optional() uses the process.cwd() directory as it's base, meaning the path you give it must be relative to that, whereas require() allows you to include relative to the file that contains the require() call -- so optional() isn't just a drop-in replacement for require() calls in some cases.

So in the example above, the process.cwd() directory would be /home/kflorence/dev/project/foo which is why using optional("../baz/qux") from a file within the /home/kflorence/dev/project/foo/bar folder would fail to find /home/kflorence/dev/project/foo/baz/qux whereas require() would succeed.

While I don't think this is a bug, it also wasn't intuitive to me at first as I expected it to work in the same way as require().

kflorence avatar Aug 14 '14 23:08 kflorence

@kflorence i believe i resolved this one too, can you confirm?

tony-o avatar Dec 04 '14 21:12 tony-o

@tony-o Relative includes are only fixed for modules like "./foo/bar" -- the current solution doesn't work correctly in cases like "../../foo/bar"

kflorence avatar Dec 04 '14 21:12 kflorence

Tried to fix this with:

try{
  if(required[0] in {".":1}){
    let pathToFile = module.parent.filename;
    let dirOfCallee = pathToFile.substr(0, pathToFile.lastIndexOf('/'))
    required = path.resolve(dirOfCallee, required);
  }
  return require(required);
}

But apparently node modules are cached, which is good, but module.parent is also cached, so basically it will work the first time you call it, but the second time, if you call optional(./file.js) from a different file on a different path - than module.parent.filename will stay the same as it was for the first call :confused:

Hope this helps.

Edit: require-new might be useful here.

panstav avatar Jan 31 '16 18:01 panstav

I wrote a module that should handle relative paths: https://github.com/fengb/require-optional

fengb avatar Apr 11 '17 00:04 fengb