node-optional
node-optional copied to clipboard
Doesn't always work with relative paths
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
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
?
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 i believe i resolved this one too, can you confirm?
@tony-o Relative includes are only fixed for modules like "./foo/bar" -- the current solution doesn't work correctly in cases like "../../foo/bar"
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.
I wrote a module that should handle relative paths: https://github.com/fengb/require-optional