RobLoach / require-one

:fishing_pole_and_fish: Require the first found module from an array.
http://npm.im/require-one
MIT License
2 stars 0 forks source link

Relative paths don't work. #1

Open FlorianWendelborn opened 9 years ago

FlorianWendelborn commented 9 years ago
var requireOne = require('require-one');
var packageName = requireOne(['../package-name', 'package-name']);

Could not found one of the expected packages.

It starts fine with a normal require of ../package-name.

EDIT: It also works fine when using __dirname + '/../package-name'

RobLoach commented 9 years ago

Interestin, does it work if you use ./../package name ? It pretty much just uses whatever node gives us.

FlorianWendelborn commented 9 years ago

Nope. It doesn't work. But it works when using a normal require with ./../package-name instead of require-one.

RobLoach commented 9 years ago

Should it use https://nodejs.org/docs/latest/api/path.html#path_path_resolve_from_to or https://nodejs.org/api/globals.html#globals_require_resolve to check the location?

FlorianWendelborn commented 9 years ago

No idea. I'd try path resolve though, because it seems to give you more options.

RobLoach commented 8 years ago

Oh, it's because the relative path from ./ is run from index.js from require-one.js. Not quite sure how to specify where relative paths should be from. You know?

FlorianWendelborn commented 8 years ago

I have an idea how this behaviour can be improved.

Consider this:

// index.js
var mod = require('./module.js');
// module.js
console.log(process.mainModule.filename)

That could be a start, but still includes weird behaviour, when you don't require from the main module. Alternatively you could maybe add an option to pass __dirname. Other than that I think it may be shomehow possible to know what required your module, but I don't know how. Maybe ask a question on stackoverflow.

There also is a require.main.filename property, which might be a little bit different.

RobLoach commented 8 years ago

@dodekeract You're right about __dirname.... requireOne([__dirname + '/module.js']);

cspotcode commented 7 years ago

How about passing the require function as an argument? requireOne will use the provided require function, meaning all relative and funky nested node_modules paths will resolve correctly.

// Node example:
requireOne(['./index', './other', 'npm-module'], require);

// An alternate API that makes it a required argument
requireOne(require)(['./index', './other', 'npm-module']);
requireOne(require, ['./index', './other', 'npm-module']);

That will work perfectly in node. However...

You will run into problems in environments such as webpack that use static analysis to detect and transform require() calls. For those environments, require is not a value at runtime and can't be passed into other functions. In those situations, requireOne can accept functions instead of strings. It will attempt to execute each function in order, stopping at the first one that doesn't throw an error.

const libFoo = requireOne([() => require('./index'), () => require('./other'), () => require('npm-module')]);

Webpack can transform that code correctly:

var libFoo = requireOne([() => __webpack_require__(10), () => __webpack_require__(11), () => __webpack_require__(27)]);
RobLoach commented 7 years ago

That's a great idea :+1: