Skip to content

Commit

Permalink
module: add createRequire method
Browse files Browse the repository at this point in the history
This is an abstraction on top of creatRequireFromPath that can accept
both paths, URL Strings, and URL Objects.
  • Loading branch information
MylesBorins committed May 2, 2019
1 parent e5c8be2 commit e5bfad2
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 4 deletions.
14 changes: 14 additions & 0 deletions doc/api/deprecations.md
Expand Up @@ -2439,6 +2439,19 @@ The `_channel` property of child process objects returned by `spawn()` and
similar functions is not intended for public use. Use `ChildProcess.channel`
instead.
<a id="DEP0130"></a>
### DEP0130: Module.createRequireFromPath()
<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/27405
description: Documentation-only.
-->
Type: Documentation-only
Module.createRequireFromPath() is deprecated. Please use [`module.createRequire()`][] instead.
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
Expand Down Expand Up @@ -2486,6 +2499,7 @@ instead.
[`http.request()`]: http.html#http_http_request_options_callback
[`https.get()`]: https.html#https_https_get_options_callback
[`https.request()`]: https.html#https_https_request_options_callback
[`module.createRequire()`]: modules.html#modules_module_createrequire_filename
[`os.networkInterfaces()`]: os.html#os_os_networkinterfaces
[`os.tmpdir()`]: os.html#os_os_tmpdir
[`process.env`]: process.html#process_process_env
Expand Down
22 changes: 22 additions & 0 deletions doc/api/modules.md
Expand Up @@ -905,15 +905,36 @@ by the [module wrapper][]. To access it, require the `Module` module:
const builtin = require('module').builtinModules;
```

### module.createRequire(filename)
<!-- YAML
added: REPLACEME
-->

* `filename` {string|URL} Filename to be used to construct the require
function. Must be a file URL object, file URL string, or absolute path
string.
* Returns: {require} Require function

```js
const { createRequire } = require('module');
const requireUtil = createRequire(require.resolve('../src/utils/'));

// Require `../src/utils/some-tool`
requireUtil('./some-tool');
```

### module.createRequireFromPath(filename)
<!-- YAML
added: v10.12.0
deprecated: REPLACEME
-->

* `filename` {string} Filename to be used to construct the relative require
function.
* Returns: {require} Require function

> Stability: 0 - Deprecated: Please use [`createRequire()`][] instead.
```js
const { createRequireFromPath } = require('module');
const requireUtil = createRequireFromPath('../src/utils/');
Expand All @@ -926,6 +947,7 @@ requireUtil('./some-tool');
[`Error`]: errors.html#errors_class_error
[`__dirname`]: #modules_dirname
[`__filename`]: #modules_filename
[`createRequire()`]: #modules_module_createrequire_filename
[`module` object]: #modules_the_module_object
[`path.dirname()`]: path.html#path_path_dirname_path
[exports shortcut]: #modules_exports_shortcut
Expand Down
33 changes: 30 additions & 3 deletions lib/internal/modules/cjs/loader.js
Expand Up @@ -24,7 +24,7 @@
const { JSON, Object, Reflect } = primordials;

const { NativeModule } = require('internal/bootstrap/loaders');
const { pathToFileURL } = require('internal/url');
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
const { deprecate } = require('internal/util');
const vm = require('vm');
const assert = require('internal/assert');
Expand Down Expand Up @@ -824,7 +824,7 @@ Module.runMain = function() {
Module._load(process.argv[1], null, true);
};

Module.createRequireFromPath = (filename) => {
function createRequireFromPath(filename) {
// Allow a directory to be passed as the filename
const trailingSlash =
filename.endsWith(path.sep) || path.sep !== '/' && filename.endsWith('\\');
Expand All @@ -838,7 +838,34 @@ Module.createRequireFromPath = (filename) => {

m.paths = Module._nodeModulePaths(m.path);
return makeRequireFunction(m);
};
}

Module.createRequireFromPath = createRequireFromPath;

const createRequireError = 'must be a file URL object, file URL string, or' +
'absolute path string';

function createRequire(filename) {
let filepath;
if (typeof filename === 'object' && !(filename instanceof URL)) {
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
} else if (typeof filename === 'object' ||
typeof filename === 'string' && !path.isAbsolute(filename)) {
try {
filepath = fileURLToPath(filename);
} catch {
throw new ERR_INVALID_ARG_VALUE('filename', filename,
createRequireError);
}
} else if (typeof filename !== 'string') {
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
} else {
filepath = filename;
}
return createRequireFromPath(filepath);
}

Module.createRequire = createRequire;

Module._initPaths = function() {
var homeDir;
Expand Down
24 changes: 23 additions & 1 deletion test/parallel/test-module-create-require.js
Expand Up @@ -4,9 +4,31 @@ require('../common');
const assert = require('assert');
const path = require('path');

const { createRequireFromPath } = require('module');
const { createRequire, createRequireFromPath } = require('module');

const p = path.resolve(__dirname, '..', 'fixtures', 'fake.js');
const u = new URL(`file://${p}`);

const req = createRequireFromPath(p);
assert.strictEqual(req('./baz'), 'perhaps I work');

const reqToo = createRequire(u);
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });

assert.throws(() => {
createRequire('https://github.com/nodejs/node/pull/27405/');
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

assert.throws(() => {
createRequire('../');
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

assert.throws(() => {
createRequire({});
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

0 comments on commit e5bfad2

Please sign in to comment.