diff --git a/doc/api/modules.md b/doc/api/modules.md index f7934706d6b0de..9919a675169e8b 100644 --- a/doc/api/modules.md +++ b/doc/api/modules.md @@ -888,12 +888,30 @@ by the [module wrapper][]. To access it, require the `Module` module: const builtin = require('module').builtinModules; ``` +### module.createRequireFromPath(filename) + + +* `filename` {string} Filename to be used to construct the relative require + function. +* Returns: {[`require`][]} Require function + +```js +const { createRequireFromPath } = require('module'); +const requireUtil = createRequireFromPath('../src/utils'); + +// require `../src/utils/some-tool` +requireUtil('./some-tool'); +``` + [`__dirname`]: #modules_dirname [`__filename`]: #modules_filename [`Error`]: errors.html#errors_class_error [`module` object]: #modules_the_module_object [`path.dirname()`]: path.html#path_path_dirname_path [GLOBAL_FOLDERS]: #modules_loading_from_the_global_folders +[`require`]: #modules_require [exports shortcut]: #modules_exports_shortcut [module resolution]: #modules_all_together [module wrapper]: #modules_the_module_wrapper diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 86ed3ac1a96fba..3a983fd7bcf00f 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -23,6 +23,7 @@ const { internalBinding, NativeModule } = require('internal/bootstrap/loaders'); const util = require('util'); +const { pathToFileURL } = require('internal/url'); const vm = require('vm'); const assert = require('assert').ok; const fs = require('fs'); @@ -54,7 +55,6 @@ module.exports = Module; let asyncESM; let ModuleJob; let createDynamicModule; -let pathToFileURL; let decorateErrorStack; function lazyLoadESM() { @@ -63,7 +63,6 @@ function lazyLoadESM() { createDynamicModule = require( 'internal/modules/esm/create_dynamic_module'); decorateErrorStack = require('internal/util').decorateErrorStack; - pathToFileURL = require('internal/url').pathToFileURL; } const { @@ -750,6 +749,13 @@ Module.runMain = function() { process._tickCallback(); }; +Module.createRequireFromPath = (filename) => { + const m = new Module(filename); + m.filename = filename; + m.paths = Module._nodeModulePaths(path.dirname(filename)); + return makeRequireFunction(m); +}; + Module._initPaths = function() { var homeDir; var nodePath; diff --git a/test/parallel/test-module-create-require.js b/test/parallel/test-module-create-require.js new file mode 100644 index 00000000000000..03ed31939fba67 --- /dev/null +++ b/test/parallel/test-module-create-require.js @@ -0,0 +1,12 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const path = require('path'); + +const { createRequireFromPath } = require('module'); + +const p = path.resolve(__dirname, '..', 'fixtures', 'fake.js'); + +const req = createRequireFromPath(p); +assert.strictEqual(req('./baz'), 'perhaps I work');