console/patches/@oclif__core@2.8.5.patch

241 lines
9.2 KiB
Diff
Raw Normal View History

2023-06-27 19:25:49 +00:00
diff --git a/lib/module-loader.js b/lib/module-loader.js
index e28f1254473d53c5f0b21c390f19ced16dc1d27b..4907936a8252e02f59145bd3297512d93302d4d8 100644
--- a/lib/module-loader.js
+++ b/lib/module-loader.js
@@ -127,7 +127,21 @@ class ModuleLoader {
return config.type !== undefined;
};
try {
- filePath = require.resolve(modulePath);
+ try {
+ // We wrap it with try/catch and fallback to custom path if it fails to make it compatible with Hive.
+ // Due to some weird behavior in tsup/esbuild, it fails to resolve the path to the module.
+ filePath = require.resolve(modulePath);
+ } catch (error) {
+ const customPath = process.env.OCLIF_CLI_CUSTOM_PATH;
+ if (typeof customPath !== "string") {
+ throw error;
+ }
+ modulePath = modulePath.replace('/src/', '/dist/').replace('\\src\\', '\\dist\\');
+ filePath = require.resolve(
+ path.resolve(customPath, modulePath) + ".js"
+ );
+ }
+
isESM = ModuleLoader.isPathModule(filePath);
}
catch {
diff --git a/lib/module-loader.modified.js b/lib/module-loader.modified.js
new file mode 100644
index 0000000000000000000000000000000000000000..bd3bf6cda2c0537590ee13860bbe36fbfb3c24d3
--- /dev/null
+++ b/lib/module-loader.modified.js
@@ -0,0 +1,208 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const path = require("path");
+const url = require("url");
+const fs = require("fs-extra");
+const errors_1 = require("./errors");
+const Config = require("./config");
+const getPackageType = require("get-package-type");
+/**
+ * Defines file extension resolution when source files do not have an extension.
+ */
+// eslint-disable-next-line camelcase
+const s_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs"];
+/**
+ * Provides a mechanism to use dynamic import / import() with tsconfig -> module: commonJS as otherwise import() gets
+ * transpiled to require().
+ */
+const _importDynamic = new Function("modulePath", "return import(modulePath)"); // eslint-disable-line no-new-func
+/**
+ * Provides a static class with several utility methods to work with Oclif config / plugin to load ESM or CJS Node
+ * modules and source files.
+ *
+ * @author Michael Leahy <support@typhonjs.io> (https://github.com/typhonrt)
+ */
+// eslint-disable-next-line unicorn/no-static-only-class
+class ModuleLoader {
+ /**
+ * Loads and returns a module.
+ *
+ * Uses `getPackageType` to determine if `type` is set to 'module. If so loads '.js' files as ESM otherwise uses
+ * a bare require to load as CJS. Also loads '.mjs' files as ESM.
+ *
+ * Uses dynamic import to load ESM source or require for CommonJS.
+ *
+ * A unique error, ModuleLoadError, combines both CJS and ESM loader module not found errors into a single error that
+ * provides a consistent stack trace and info.
+ *
+ * @param {IConfig|IPlugin} config - Oclif config or plugin config.
+ * @param {string} modulePath - NPM module name or file path to load.
+ *
+ * @returns {Promise<*>} The entire ESM module from dynamic import or CJS module by require.
+ */
+ static async load(config, modulePath) {
+ let filePath;
+ let isESM;
+ try {
+ ({ isESM, filePath } = ModuleLoader.resolvePath(config, modulePath));
+ // It is important to await on _importDynamic to catch the error code.
+ return isESM
+ ? await _importDynamic(url.pathToFileURL(filePath))
+ : require(filePath);
+ } catch (error) {
+ if (
+ error.code === "MODULE_NOT_FOUND" ||
+ error.code === "ERR_MODULE_NOT_FOUND"
+ ) {
+ throw new errors_1.ModuleLoadError(
+ `${isESM ? "import()" : "require"} failed to load ${
+ filePath || modulePath
+ }`
+ );
+ }
+ throw error;
+ }
+ }
+ /**
+ * Loads a module and returns an object with the module and data about the module.
+ *
+ * Uses `getPackageType` to determine if `type` is set to `module`. If so loads '.js' files as ESM otherwise uses
+ * a bare require to load as CJS. Also loads '.mjs' files as ESM.
+ *
+ * Uses dynamic import to load ESM source or require for CommonJS.
+ *
+ * A unique error, ModuleLoadError, combines both CJS and ESM loader module not found errors into a single error that
+ * provides a consistent stack trace and info.
+ *
+ * @param {IConfig|IPlugin} config - Oclif config or plugin config.
+ * @param {string} modulePath - NPM module name or file path to load.
+ *
+ * @returns {Promise<{isESM: boolean, module: *, filePath: string}>} An object with the loaded module & data including
+ * file path and whether the module is ESM.
+ */
+ static async loadWithData(config, modulePath) {
+ let filePath;
+ let isESM;
+ try {
+ ({ isESM, filePath } = ModuleLoader.resolvePath(config, modulePath));
+ const module = isESM
+ ? await _importDynamic(url.pathToFileURL(filePath))
+ : require(filePath);
+ return { isESM, module, filePath };
+ } catch (error) {
+ if (
+ error.code === "MODULE_NOT_FOUND" ||
+ error.code === "ERR_MODULE_NOT_FOUND"
+ ) {
+ throw new errors_1.ModuleLoadError(
+ `${isESM ? "import()" : "require"} failed to load ${
+ filePath || modulePath
+ }: ${error.message}`
+ );
+ }
+ throw error;
+ }
+ }
+ /**
+ * For `.js` files uses `getPackageType` to determine if `type` is set to `module` in associated `package.json`. If
+ * the `modulePath` provided ends in `.mjs` it is assumed to be ESM.
+ *
+ * @param {string} filePath - File path to test.
+ *
+ * @returns {boolean} The modulePath is an ES Module.
+ * @see https://www.npmjs.com/package/get-package-type
+ */
+ static isPathModule(filePath) {
+ const extension = path.extname(filePath).toLowerCase();
+ switch (extension) {
+ case ".js":
+ return getPackageType.sync(filePath) === "module";
+ case ".ts":
+ return getPackageType.sync(filePath) === "module";
+ case ".mjs":
+ return true;
+ default:
+ return false;
+ }
+ }
+ /**
+ * Resolves a modulePath first by `require.resolve` to allow Node to resolve an actual module. If this fails then
+ * the `modulePath` is resolved from the root of the provided config. `Config.tsPath` is used for initial resolution.
+ * If this file path does not exist then several extensions are tried from `s_EXTENSIONS` in order: '.js', '.mjs',
+ * '.cjs'. After a file path has been selected `isPathModule` is used to determine if the file is an ES Module.
+ *
+ * @param {IConfig|IPlugin} config - Oclif config or plugin config.
+ * @param {string} modulePath - File path to load.
+ *
+ * @returns {{isESM: boolean, filePath: string}} An object including file path and whether the module is ESM.
+ */
+ static resolvePath(config, modulePath) {
+ let isESM;
+ let filePath;
+ const isPlugin = (config) => {
+ return config.type !== undefined;
+ };
+ try {
+ try {
+ // We wrap it with try/catch and fallback to custom path if it fails to make it compatible with Hive.
+ // Due to some weird behavior in tsup/esbuild, it fails to resolve the path to the module.
+ filePath = require.resolve(modulePath);
+ } catch (error) {
+ const customPath = process.env.OCLIF_CLI_CUSTOM_PATH;
+ if (typeof customPath !== "string") {
+ throw error;
+ }
+ filePath = require.resolve(
+ path.resolve(customPath, modulePath) + ".js"
+ );
+ }
+ isESM = ModuleLoader.isPathModule(filePath);
+ } catch {
+ filePath = isPlugin(config)
+ ? Config.tsPath(config.root, modulePath, config.type)
+ : Config.tsPath(config.root, modulePath);
+ let fileExists = false;
+ let isDirectory = false;
+ if (fs.existsSync(filePath)) {
+ fileExists = true;
+ try {
+ if (fs.lstatSync(filePath)?.isDirectory?.()) {
+ fileExists = false;
+ isDirectory = true;
+ }
+ } catch {}
+ }
+ if (!fileExists) {
+ // Try all supported extensions.
+ let foundPath = ModuleLoader.findFile(filePath);
+ if (!foundPath && isDirectory) {
+ // Since filePath is a directory, try looking for index file.
+ foundPath = ModuleLoader.findFile(path.join(filePath, "index"));
+ }
+ if (foundPath) {
+ filePath = foundPath;
+ }
+ }
+ isESM = ModuleLoader.isPathModule(filePath);
+ }
+ return { isESM, filePath };
+ }
+ /**
+ * Try adding the different extensions from `s_EXTENSIONS` to find the file.
+ *
+ * @param {string} filePath - File path to load.
+ *
+ * @returns {string | null} Modified file path including extension or null if file is not found.
+ */
+ static findFile(filePath) {
+ // eslint-disable-next-line camelcase
+ for (const extension of s_EXTENSIONS) {
+ const testPath = `${filePath}${extension}`;
+ if (fs.existsSync(testPath)) {
+ return testPath;
+ }
+ }
+ return null;
+ }
+}
+exports.default = ModuleLoader;