UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

221 lines (220 loc) • 9.3 kB
"use strict"; // This file contains methods and utilities that should **only** be used by the plugin worker. Object.defineProperty(exports, "__esModule", { value: true }); exports.unregisterPluginTSTranspiler = void 0; exports.readPluginPackageJson = readPluginPackageJson; exports.resolveLocalNxPlugin = resolveLocalNxPlugin; exports.registerPluginTSTranspiler = registerPluginTSTranspiler; exports.getPluginPathAndName = getPluginPathAndName; exports.loadNxPlugin = loadNxPlugin; exports.loadNxPluginAsync = loadNxPluginAsync; const posix_1 = require("node:path/posix"); const installation_directory_1 = require("../../utils/installation-directory"); const package_json_1 = require("../../utils/package-json"); const fileutils_1 = require("../../utils/fileutils"); const workspace_root_1 = require("../../utils/workspace-root"); const node_fs_1 = require("node:fs"); const register_1 = require("../../plugins/js/utils/register"); const find_project_for_path_1 = require("../utils/find-project-for-path"); const path_1 = require("../../utils/path"); const logger_1 = require("../../utils/logger"); const node_path_1 = require("node:path"); const retrieve_workspace_files_1 = require("../utils/retrieve-workspace-files"); const utils_1 = require("./utils"); const internal_api_1 = require("./internal-api"); const error_types_1 = require("../error-types"); const path = require("node:path/posix"); const typescript_1 = require("../../plugins/js/utils/typescript"); function readPluginPackageJson(pluginName, projects, paths = (0, installation_directory_1.getNxRequirePaths)()) { try { const result = (0, package_json_1.readModulePackageJsonWithoutFallbacks)(pluginName, paths); return { json: result.packageJson, path: result.path, }; } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { const localPluginPath = resolveLocalNxPlugin(pluginName, projects); if (localPluginPath) { const localPluginPackageJson = path.join(localPluginPath.path, 'package.json'); if (!exports.unregisterPluginTSTranspiler) { registerPluginTSTranspiler(); } return { path: localPluginPackageJson, json: (0, fileutils_1.readJsonFile)(localPluginPackageJson), }; } } throw e; } } function resolveLocalNxPlugin(importPath, projects, root = workspace_root_1.workspaceRoot) { return lookupLocalPlugin(importPath, projects, root); } exports.unregisterPluginTSTranspiler = null; /** * Register swc-node or ts-node if they are not currently registered * with some default settings which work well for Nx plugins. */ function registerPluginTSTranspiler() { // Get the first tsconfig that matches the allowed set const tsConfigName = [ (0, posix_1.join)(workspace_root_1.workspaceRoot, 'tsconfig.base.json'), (0, posix_1.join)(workspace_root_1.workspaceRoot, 'tsconfig.json'), ].find((x) => (0, node_fs_1.existsSync)(x)); if (!tsConfigName) { return; } const tsConfig = tsConfigName ? (0, typescript_1.readTsConfig)(tsConfigName) : {}; const cleanupFns = [ (0, register_1.registerTsConfigPaths)(tsConfigName), (0, register_1.registerTranspiler)({ experimentalDecorators: true, emitDecoratorMetadata: true, ...tsConfig.options, }, tsConfig.raw), ]; exports.unregisterPluginTSTranspiler = () => { cleanupFns.forEach((fn) => fn?.()); }; } function lookupLocalPlugin(importPath, projects, root = workspace_root_1.workspaceRoot) { const projectConfig = findNxProjectForImportPath(importPath, projects, root); if (!projectConfig) { return null; } return { path: path.join(root, projectConfig.root), projectConfig }; } function findNxProjectForImportPath(importPath, projects, root = workspace_root_1.workspaceRoot) { const tsConfigPaths = readTsConfigPaths(root); const possiblePaths = tsConfigPaths[importPath]?.map((p) => (0, path_1.normalizePath)(path.relative(root, path.join(root, p)))); if (possiblePaths?.length) { const projectRootMappings = new Map(); const projectNameMap = new Map(); for (const projectRoot in projects) { const project = projects[projectRoot]; projectRootMappings.set(project.root, project.name); projectNameMap.set(project.name, project); } for (const tsConfigPath of possiblePaths) { const nxProject = (0, find_project_for_path_1.findProjectForPath)(tsConfigPath, projectRootMappings); if (nxProject) { return projectNameMap.get(nxProject); } } logger_1.logger.verbose('Unable to find local plugin', possiblePaths, projectRootMappings); throw new Error('Unable to resolve local plugin with import path ' + importPath); } } let tsconfigPaths; function readTsConfigPaths(root = workspace_root_1.workspaceRoot) { if (!tsconfigPaths) { const tsconfigPath = ['tsconfig.base.json', 'tsconfig.json'] .map((x) => path.join(root, x)) .filter((x) => (0, node_fs_1.existsSync)(x))[0]; if (!tsconfigPath) { throw new Error('unable to find tsconfig.base.json or tsconfig.json'); } const { compilerOptions } = (0, fileutils_1.readJsonFile)(tsconfigPath); tsconfigPaths = compilerOptions?.paths; } return tsconfigPaths ?? {}; } function readPluginMainFromProjectConfiguration(plugin) { const { main } = Object.values(plugin.targets).find((x) => [ '@nx/js:tsc', '@nrwl/js:tsc', '@nx/js:swc', '@nrwl/js:swc', '@nx/node:package', '@nrwl/node:package', ].includes(x.executor))?.options || plugin.targets?.build?.options || {}; return main; } function getPluginPathAndName(moduleName, paths, projects, root) { let pluginPath; let registerTSTranspiler = false; try { pluginPath = require.resolve(moduleName, { paths, }); const extension = path.extname(pluginPath); registerTSTranspiler = extension === '.ts'; } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { const plugin = resolveLocalNxPlugin(moduleName, projects, root); if (plugin) { registerTSTranspiler = true; const main = readPluginMainFromProjectConfiguration(plugin.projectConfig); pluginPath = main ? path.join(root, main) : plugin.path; } else { logger_1.logger.error(`Plugin listed in \`nx.json\` not found: ${moduleName}`); throw e; } } else { throw e; } } const packageJsonPath = path.join(pluginPath, 'package.json'); // Register the ts-transpiler if we are pointing to a // plain ts file that's not part of a plugin project if (registerTSTranspiler) { registerPluginTSTranspiler(); } const { name } = !['.ts', '.js'].some((x) => (0, node_path_1.extname)(moduleName) === x) && // Not trying to point to a ts or js file (0, node_fs_1.existsSync)(packageJsonPath) // plugin has a package.json ? (0, fileutils_1.readJsonFile)(packageJsonPath) // read name from package.json : { name: moduleName }; return { pluginPath, name }; } let projectsWithoutInference; function loadNxPlugin(plugin, root) { return [ loadNxPluginAsync(plugin, (0, installation_directory_1.getNxRequirePaths)(root), root), () => { }, ]; } async function loadNxPluginAsync(pluginConfiguration, paths, root) { const moduleName = typeof pluginConfiguration === 'string' ? pluginConfiguration : pluginConfiguration.plugin; try { try { require.resolve(moduleName); } catch { // If a plugin cannot be resolved, we will need projects to resolve it projectsWithoutInference ??= await (0, retrieve_workspace_files_1.retrieveProjectConfigurationsWithoutPluginInference)(root); } performance.mark(`Load Nx Plugin: ${moduleName} - start`); let { pluginPath, name } = await getPluginPathAndName(moduleName, paths, projectsWithoutInference, root); const plugin = (0, utils_1.normalizeNxPlugin)(await importPluginModule(pluginPath)); plugin.name ??= name; performance.mark(`Load Nx Plugin: ${moduleName} - end`); performance.measure(`Load Nx Plugin: ${moduleName}`, `Load Nx Plugin: ${moduleName} - start`, `Load Nx Plugin: ${moduleName} - end`); return new internal_api_1.LoadedNxPlugin(plugin, pluginConfiguration); } catch (e) { throw new error_types_1.LoadPluginError(moduleName, e); } } async function importPluginModule(pluginPath) { const m = await Promise.resolve(`${pluginPath}`).then(s => require(s)); if (m.default && ('createNodes' in m.default || 'createNodesV2' in m.default || 'createDependencies' in m.default)) { return m.default; } return m; }