82 lines
2.5 KiB
Plaintext
82 lines
2.5 KiB
Plaintext
/**
|
|
* @fileoverview Universal module importer
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Imports
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const { createRequire } = require("module");
|
|
const { pathToFileURL } = require("url");
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Helpers
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const SLASHES = new Set(["/", "\\"]);
|
|
|
|
/**
|
|
* Normalizes directories to have a trailing slash.
|
|
* Resolve is pretty finicky -- if the directory name doesn't have
|
|
* a trailing slash then it tries to look in the parent directory.
|
|
* i.e., if the directory is "/usr/nzakas/foo" it will start the
|
|
* search in /usr/nzakas. However, if the directory is "/user/nzakas/foo/",
|
|
* then it will start the search in /user/nzakas/foo.
|
|
* @param {string} directory The directory to check.
|
|
* @returns {string} The normalized directory.
|
|
*/
|
|
function normalizeDirectory(directory) {
|
|
if (!SLASHES.has(directory[directory.length-1])) {
|
|
return directory + "/";
|
|
}
|
|
|
|
return directory;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Exports
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Class for importing both CommonJS and ESM modules in Node.js.
|
|
*/
|
|
exports.ModuleImporter = class ModuleImporter {
|
|
|
|
/**
|
|
* Creates a new instance.
|
|
* @param {string} [cwd] The current working directory to resolve from.
|
|
*/
|
|
constructor(cwd = process.cwd()) {
|
|
|
|
/**
|
|
* The base directory from which paths should be resolved.
|
|
* @type {string}
|
|
*/
|
|
this.cwd = normalizeDirectory(cwd);
|
|
}
|
|
|
|
/**
|
|
* Resolves a module based on its name or location.
|
|
* @param {string} specifier Either an npm package name or
|
|
* relative file path.
|
|
* @returns {string|undefined} The location of the import.
|
|
* @throws {Error} If specifier cannot be located.
|
|
*/
|
|
resolve(specifier) {
|
|
const require = createRequire(this.cwd);
|
|
return require.resolve(specifier);
|
|
}
|
|
|
|
/**
|
|
* Imports a module based on its name or location.
|
|
* @param {string} specifier Either an npm package name or
|
|
* relative file path.
|
|
* @returns {Promise<object>} The module's object.
|
|
*/
|
|
import(specifier) {
|
|
const location = this.resolve(specifier);
|
|
return import(pathToFileURL(location).href);
|
|
}
|
|
|
|
}
|