UNPKG

nx

Version:

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

340 lines (339 loc) 14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.patternsWeIgnoreInCommunityReport = exports.packagesWeCareAbout = void 0; exports.reportHandler = reportHandler; exports.getReportData = getReportData; exports.findMisalignedPackagesForPackage = findMisalignedPackagesForPackage; exports.findInstalledPowerpackPlugins = findInstalledPowerpackPlugins; exports.findInstalledCommunityPlugins = findInstalledCommunityPlugins; exports.findRegisteredPluginsBeingUsed = findRegisteredPluginsBeingUsed; exports.findInstalledPackagesWeCareAbout = findInstalledPackagesWeCareAbout; const chalk = require("chalk"); const output_1 = require("../../utils/output"); const path_1 = require("path"); const package_manager_1 = require("../../utils/package-manager"); const fileutils_1 = require("../../utils/fileutils"); const package_json_1 = require("../../utils/package-json"); const local_plugins_1 = require("../../utils/plugins/local-plugins"); const project_graph_1 = require("../../project-graph/project-graph"); const semver_1 = require("semver"); const installed_plugins_1 = require("../../utils/plugins/installed-plugins"); const installation_directory_1 = require("../../utils/installation-directory"); const nx_json_1 = require("../../config/nx-json"); const error_types_1 = require("../../project-graph/error-types"); const nx_key_1 = require("../../utils/nx-key"); const cache_1 = require("../../tasks-runner/cache"); const native_1 = require("../../native"); const cache_directory_1 = require("../../utils/cache-directory"); const nxPackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(__dirname, '../../../package.json')); exports.packagesWeCareAbout = [ 'lerna', ...nxPackageJson['nx-migrations'].packageGroup.map((x) => typeof x === 'string' ? x : x.package), '@nrwl/schematics', // manually added since we don't publish it anymore. 'typescript', ]; exports.patternsWeIgnoreInCommunityReport = [ ...exports.packagesWeCareAbout, new RegExp('@nx/powerpack*'), '@schematics/angular', new RegExp('@angular/*'), '@nestjs/schematics', ]; const LINE_SEPARATOR = '---------------------------------------'; /** * Reports relevant version numbers for adding to an Nx issue report * * @remarks * * Must be run within an Nx workspace * */ async function reportHandler() { const { pm, pmVersion, nxKey, nxKeyError, localPlugins, powerpackPlugins, communityPlugins, registeredPlugins, packageVersionsWeCareAbout, outOfSyncPackageGroup, projectGraphError, nativeTarget, cache, } = await getReportData(); const fields = [ ['Node', process.versions.node], ['OS', `${process.platform}-${process.arch}`], ['Native Target', nativeTarget ?? 'Unavailable'], [pm, pmVersion], ]; let padding = Math.max(...fields.map((f) => f[0].length)); const bodyLines = fields.map(([field, value]) => `${field.padEnd(padding)} : ${value}`); bodyLines.push(''); padding = Math.max(...packageVersionsWeCareAbout.map((x) => x.package.length)) + 1; packageVersionsWeCareAbout.forEach((p) => { bodyLines.push(`${chalk.green(p.package.padEnd(padding))} : ${chalk.bold(p.version)}`); }); if (nxKey) { bodyLines.push(''); bodyLines.push(LINE_SEPARATOR); bodyLines.push(chalk.green('Nx key licensed packages')); bodyLines.push((0, nx_key_1.createNxKeyLicenseeInformation)(nxKey)); if (nxKey.realExpiresAt || nxKey.expiresAt) { const licenseExpiryDate = new Date((nxKey.realExpiresAt ?? nxKey.expiresAt) * 1000); // license is not expired if (licenseExpiryDate.getTime() >= Date.now()) { if ('perpetualNxVersion' in nxKey) { bodyLines.push(`License expires on ${licenseExpiryDate.toLocaleDateString()}, but will continue to work with Nx ${nxKey.perpetualNxVersion} and below.`); } else { bodyLines.push(`License expires on ${licenseExpiryDate.toLocaleDateString()}.`); } } else { if ('perpetualNxVersion' in nxKey) { bodyLines.push(`License expired on ${licenseExpiryDate.toLocaleDateString()}, but will continue to work with Nx ${nxKey.perpetualNxVersion} and below.`); } else { bodyLines.push(`License expired on ${licenseExpiryDate.toLocaleDateString()}.`); } } } bodyLines.push(''); padding = Math.max(...powerpackPlugins.map((powerpackPlugin) => powerpackPlugin.name.length)) + 1; for (const powerpackPlugin of powerpackPlugins) { bodyLines.push(`${chalk.green(powerpackPlugin.name.padEnd(padding))} : ${chalk.bold(powerpackPlugin.version)}`); } bodyLines.push(''); } else if (nxKeyError) { bodyLines.push(''); bodyLines.push(chalk.red('Nx key')); bodyLines.push(LINE_SEPARATOR); bodyLines.push(nxKeyError.message); bodyLines.push(''); } if (registeredPlugins.length) { bodyLines.push(LINE_SEPARATOR); bodyLines.push('Registered Plugins:'); for (const plugin of registeredPlugins) { bodyLines.push(`${chalk.green(plugin)}`); } } if (communityPlugins.length) { bodyLines.push(LINE_SEPARATOR); padding = Math.max(...communityPlugins.map((x) => x.name.length)) + 1; bodyLines.push('Community plugins:'); communityPlugins.forEach((p) => { bodyLines.push(`${chalk.green(p.name.padEnd(padding))}: ${chalk.bold(p.version)}`); }); } if (localPlugins.length) { bodyLines.push(LINE_SEPARATOR); bodyLines.push('Local workspace plugins:'); for (const plugin of localPlugins) { bodyLines.push(`\t ${chalk.green(plugin)}`); } } if (cache) { bodyLines.push(LINE_SEPARATOR); bodyLines.push(`Cache Usage: ${(0, cache_1.formatCacheSize)(cache.used)} / ${cache.max === 0 ? '∞' : (0, cache_1.formatCacheSize)(cache.max)}`); } if (outOfSyncPackageGroup) { bodyLines.push(LINE_SEPARATOR); bodyLines.push(`The following packages should match the installed version of ${outOfSyncPackageGroup.basePackage}`); for (const pkg of outOfSyncPackageGroup.misalignedPackages) { bodyLines.push(` - ${pkg.name}@${pkg.version}`); } bodyLines.push(''); bodyLines.push(`To fix this, run \`nx migrate ${outOfSyncPackageGroup.migrateTarget}\``); } if (projectGraphError) { bodyLines.push(LINE_SEPARATOR); bodyLines.push('⚠️ Unable to construct project graph.'); bodyLines.push(projectGraphError.message); bodyLines.push(projectGraphError.stack); } output_1.output.log({ title: 'Report complete - copy this into the issue template', bodyLines, }); } async function getReportData() { const pm = (0, package_manager_1.detectPackageManager)(); const pmVersion = (0, package_manager_1.getPackageManagerVersion)(pm); const { graph, error: projectGraphError } = await tryGetProjectGraph(); const nxJson = (0, nx_json_1.readNxJson)(); const localPlugins = await findLocalPlugins(graph, nxJson); const powerpackPlugins = findInstalledPowerpackPlugins(); const communityPlugins = findInstalledCommunityPlugins(); const registeredPlugins = findRegisteredPluginsBeingUsed(nxJson); const packageVersionsWeCareAbout = findInstalledPackagesWeCareAbout(); packageVersionsWeCareAbout.unshift({ package: 'nx', version: nxPackageJson.version, }); if (globalThis.GLOBAL_NX_VERSION) { packageVersionsWeCareAbout.unshift({ package: 'nx (global)', version: globalThis.GLOBAL_NX_VERSION, }); } const outOfSyncPackageGroup = findMisalignedPackagesForPackage(nxPackageJson); const native = isNativeAvailable(); let nxKey = null; let nxKeyError = null; try { nxKey = await (0, nx_key_1.getNxKeyInformation)(); } catch (e) { if (!(e instanceof nx_key_1.NxKeyNotInstalledError)) { nxKeyError = e; } } let cache = (0, cache_1.dbCacheEnabled)(nxJson) ? { max: nxJson.maxCacheSize !== undefined ? (0, cache_1.parseMaxCacheSize)(nxJson.maxCacheSize) : (0, native_1.getDefaultMaxCacheSize)(cache_directory_1.cacheDir), used: new cache_1.DbCache({ nxCloudRemoteCache: null }).getUsedCacheSpace(), } : null; return { pm, nxKey, nxKeyError, powerpackPlugins, pmVersion, localPlugins, communityPlugins, registeredPlugins, packageVersionsWeCareAbout, outOfSyncPackageGroup, projectGraphError, nativeTarget: native ? native.getBinaryTarget() : null, cache, }; } async function tryGetProjectGraph() { try { return { graph: await (0, project_graph_1.createProjectGraphAsync)() }; } catch (error) { if (error instanceof error_types_1.ProjectGraphError) { return { graph: error.getPartialProjectGraph(), error: error, }; } return { error, }; } } async function findLocalPlugins(projectGraph, nxJson) { try { const localPlugins = await (0, local_plugins_1.getLocalWorkspacePlugins)((0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), nxJson); return Array.from(localPlugins.keys()); } catch { return []; } } function readPackageJson(p) { try { return (0, package_json_1.readModulePackageJson)(p, (0, installation_directory_1.getNxRequirePaths)()).packageJson; } catch { return null; } } function readPackageVersion(p) { return readPackageJson(p)?.version; } function findMisalignedPackagesForPackage(base) { const misalignedPackages = []; let migrateTarget = base.version; const { packageGroup } = (0, package_json_1.readNxMigrateConfig)(base); for (const entry of packageGroup ?? []) { const { package: packageName, version } = entry; // should be aligned if (version === '*') { const installedVersion = readPackageVersion(packageName); if (installedVersion && installedVersion !== base.version) { if ((0, semver_1.valid)(installedVersion) && (0, semver_1.gt)(installedVersion, migrateTarget)) { migrateTarget = installedVersion; } misalignedPackages.push({ name: packageName, version: installedVersion, }); } } } return misalignedPackages.length ? { basePackage: base.name, misalignedPackages, migrateTarget: `${base.name}@${migrateTarget}`, } : undefined; } function findInstalledPowerpackPlugins() { const installedPlugins = (0, installed_plugins_1.findInstalledPlugins)(); return installedPlugins.filter((dep) => new RegExp('@nx/powerpack*|@nx/(.+)-cache|@nx/(conformance|owners|enterprise*)').test(dep.name)); } function findInstalledCommunityPlugins() { const installedPlugins = (0, installed_plugins_1.findInstalledPlugins)(); return installedPlugins.filter((dep) => dep.name !== 'nx' && !exports.patternsWeIgnoreInCommunityReport.some((pattern) => typeof pattern === 'string' ? pattern === dep.name : pattern.test(dep.name))); } function findRegisteredPluginsBeingUsed(nxJson) { if (!nxJson.plugins) { return []; } return nxJson.plugins.map((plugin) => typeof plugin === 'object' ? plugin.plugin : plugin); } function findInstalledPackagesWeCareAbout() { const packagesWeMayCareAbout = {}; // TODO (v20): Remove workaround for hiding @nrwl packages when matching @nx package is found. const packageChangeMap = { '@nrwl/nx-plugin': '@nx/plugin', '@nx/plugin': '@nrwl/nx-plugin', '@nrwl/eslint-plugin-nx': '@nx/eslint-plugin', '@nx/eslint-plugin': '@nrwl/eslint-plugin-nx', '@nrwl/nx-cloud': 'nx-cloud', }; for (const pkg of exports.packagesWeCareAbout) { const v = readPackageVersion(pkg); if (v) { // If its a @nrwl scoped package, keep the version if there is no // corresponding @nx scoped package, or it has a different version. if (pkg.startsWith('@nrwl/')) { const otherPackage = packageChangeMap[pkg] ?? pkg.replace('@nrwl/', '@nx/'); const otherVersion = packagesWeMayCareAbout[otherPackage]; if (!otherVersion || v !== otherVersion) { packagesWeMayCareAbout[pkg] = v; } // If its a @nx scoped package, always keep the version, and // remove the corresponding @nrwl scoped package if it exists. } else if (pkg.startsWith('@nx/')) { const otherPackage = packageChangeMap[pkg] ?? pkg.replace('@nx/', '@nrwl/'); const otherVersion = packagesWeMayCareAbout[otherPackage]; if (otherVersion && v === otherVersion) { delete packagesWeMayCareAbout[otherPackage]; } packagesWeMayCareAbout[pkg] = v; } else { packagesWeMayCareAbout[pkg] = v; } } } return Object.entries(packagesWeMayCareAbout).map(([pkg, version]) => ({ package: pkg, version, })); } function isNativeAvailable() { try { return require('../../native'); } catch { return false; } }