UNPKG

@commitlint/load

Version:

Load shared commitlint configuration

157 lines 6.15 kB
import { createRequire } from "node:module"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import pc from "picocolors"; import { normalizePackageName, getShorthandName } from "./plugin-naming.js"; import { WhitespacePluginError, MissingPluginError } from "./plugin-errors.js"; import { resolveFromNpxCache } from "@commitlint/resolve-extends"; const require = createRequire(import.meta.url); const __dirname = path.resolve(fileURLToPath(import.meta.url), ".."); const dynamicImport = async (id) => { const imported = await import(path.isAbsolute(id) ? pathToFileURL(id).toString() : id); return ("default" in imported && imported.default) || imported; }; function sanitizeErrorMessage(message) { return message .replace(/\/[^/]+\/node_modules/g, "...") .replace(/\\[^\\]+\\node_modules/g, "..."); } function findPackageJson(dir) { let current = dir; const root = path.parse(dir).root; while (current !== root) { const pkgPath = path.join(current, "package.json"); if (fs.existsSync(pkgPath)) { return pkgPath; } current = path.dirname(current); } return null; } function normalizeOptions(options) { if (typeof options === "boolean") { return { debug: options }; } return options; } export default async function loadPlugin(plugins, pluginName, options = {}) { const normalized = normalizeOptions(options); const { debug = false, searchPaths = [] } = normalized; for (const searchPath of searchPaths) { if (typeof searchPath !== "string" || !path.isAbsolute(searchPath)) { throw new Error(`Invalid searchPath "${searchPath}": must be an absolute path`); } if (!fs.existsSync(searchPath)) { throw new Error(`Invalid searchPath "${searchPath}": directory does not exist`); } if (!fs.statSync(searchPath).isDirectory()) { throw new Error(`Invalid searchPath "${searchPath}": must be a directory, not a file`); } } const longName = normalizePackageName(pluginName); const shortName = getShorthandName(longName); if (pluginName.match(/\s+/u)) { throw new WhitespacePluginError(pluginName, { pluginName: longName, }); } const pluginKey = longName === pluginName ? shortName : pluginName; if (!plugins[pluginKey]) { let plugin; let resolvedPath; // Try to load from npx cache directories using require.resolve const npxResolvedPath = resolveFromNpxCache(longName); if (npxResolvedPath) { try { plugin = await dynamicImport(npxResolvedPath); resolvedPath = npxResolvedPath; } catch (err) { if (debug) { console.debug(`Failed to load plugin ${longName} from npx cache: ${err.message}`); } } } // Try to load from additional search paths (extended config's node_modules) if (!plugin) { for (const searchPath of searchPaths) { try { resolvedPath = require.resolve(longName, { paths: [searchPath] }); plugin = await dynamicImport(resolvedPath); break; } catch (err) { if (debug) { console.debug(`Failed to load plugin ${longName} from ${searchPath}: ${err.message}`); } } } } // Try default resolution as last resort if (!plugin) { try { plugin = await dynamicImport(longName); // Try to resolve path for debug logging try { resolvedPath = require.resolve(longName); } catch { // Ignore - path not critical } } catch (err) { let resolutionError; try { resolvedPath = require.resolve(longName); } catch (resolveErr) { resolutionError = resolveErr; } if (resolutionError) { // Resolution failed - throw MissingPluginError if (debug) { console.debug(`Failed to resolve plugin ${longName}: ${resolutionError.message}`); } throw new MissingPluginError(pluginName, sanitizeErrorMessage(resolutionError.message), { pluginName: longName, commitlintPath: path.resolve(__dirname, "../.."), }); } // Resolution succeeded but import failed - rethrow original error throw err; } } // This step is costly, so skip if debug is disabled if (debug) { let version = null; if (resolvedPath) { try { const pkgPath = findPackageJson(path.dirname(resolvedPath)); if (pkgPath) { version = require(pkgPath).version; } } catch { // Do nothing } } const loadedPluginAndVersion = version ? `${longName}@${version}` : `${longName}, version unknown`; const fromPath = resolvedPath ? ` (from ${resolvedPath})` : ""; console.log(pc.blue(`Loaded plugin ${pluginName} (${loadedPluginAndVersion})${fromPath}`)); } if (plugin) { plugins[pluginKey] = plugin; } else { throw new MissingPluginError(pluginName, "Plugin loaded but is undefined", { pluginName: longName, commitlintPath: path.resolve(__dirname, "../.."), }); } } return plugins; } //# sourceMappingURL=load-plugin.js.map