UNPKG

@nx/js

Version:

The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects.

203 lines (202 loc) 9.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.afterAllProjectsVersioned = void 0; const devkit_1 = require("@nx/devkit"); const node_child_process_1 = require("node:child_process"); const node_path_1 = require("node:path"); const release_1 = require("nx/release"); const npm_config_1 = require("../utils/npm-config"); const update_lock_file_1 = require("./utils/update-lock-file"); const chalk = require("chalk"); const afterAllProjectsVersioned = async (cwd, { rootVersionActionsOptions, ...opts }) => { return { changedFiles: await (0, update_lock_file_1.updateLockFile)(cwd, { ...opts, useLegacyVersioning: false, options: rootVersionActionsOptions, }), deletedFiles: [], }; }; exports.afterAllProjectsVersioned = afterAllProjectsVersioned; // Cache at the module level to avoid re-detecting the package manager for each instance let pm; class JsVersionActions extends release_1.VersionActions { constructor() { super(...arguments); this.validManifestFilenames = ['package.json']; } async readCurrentVersionFromSourceManifest(tree) { const sourcePackageJsonPath = (0, node_path_1.join)(this.projectGraphNode.data.root, 'package.json'); try { const packageJson = (0, devkit_1.readJson)(tree, sourcePackageJsonPath); return { manifestPath: sourcePackageJsonPath, currentVersion: packageJson.version, }; } catch { throw new Error(`Unable to determine the current version for project "${this.projectGraphNode.name}" from ${sourcePackageJsonPath}, please ensure that the "version" field is set within the package.json file`); } } async readCurrentVersionFromRegistry(tree, currentVersionResolverMetadata) { const sourcePackageJsonPath = (0, node_path_1.join)(this.projectGraphNode.data.root, 'package.json'); const packageJson = (0, devkit_1.readJson)(tree, sourcePackageJsonPath); const packageName = packageJson.name; const metadata = currentVersionResolverMetadata; const registryArg = typeof metadata?.registry === 'string' ? metadata.registry : undefined; const tagArg = typeof metadata?.tag === 'string' ? metadata.tag : undefined; const warnFn = (message) => { console.log(chalk.keyword('orange')(message)); }; const { registry, tag, registryConfigKey } = await (0, npm_config_1.parseRegistryOptions)(devkit_1.workspaceRoot, { packageRoot: this.projectGraphNode.data.root, packageJson, }, { registry: registryArg, tag: tagArg, }, warnFn); let currentVersion = null; try { // Must be non-blocking async to allow spinner to render currentVersion = await new Promise((resolve, reject) => { (0, node_child_process_1.exec)(`npm view ${packageName} version --"${registryConfigKey}=${registry}" --tag=${tag}`, { windowsHide: false, }, (error, stdout, stderr) => { if (error) { return reject(error); } if (stderr) { return reject(stderr); } return resolve(stdout.trim()); }); }); } catch { } return { currentVersion, // Make troubleshooting easier by including the registry and tag data in the log text logText: `"${registryConfigKey}=${registry}" tag=${tag}`, }; } async readCurrentVersionOfDependency(tree, projectGraph, dependencyProjectName) { const sourcePackageJsonPath = (0, node_path_1.join)(this.projectGraphNode.data.root, 'package.json'); const json = (0, devkit_1.readJson)(tree, sourcePackageJsonPath); // Resolve the package name from the project graph metadata, as it may not match the project name const dependencyPackageName = projectGraph.nodes[dependencyProjectName].data.metadata?.js?.packageName; const dependencyTypes = [ 'dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies', ]; let currentVersion = null; let dependencyCollection = null; for (const depType of dependencyTypes) { if (json[depType] && json[depType][dependencyPackageName]) { currentVersion = json[depType][dependencyPackageName]; dependencyCollection = depType; break; } } return { currentVersion, dependencyCollection, }; } async updateProjectVersion(tree, newVersion) { const logMessages = []; for (const manifestToUpdate of this.manifestsToUpdate) { (0, devkit_1.updateJson)(tree, manifestToUpdate.manifestPath, (json) => { json.version = newVersion; return json; }); logMessages.push(`✍️ New version ${newVersion} written to manifest: ${manifestToUpdate.manifestPath}`); } return logMessages; } async updateProjectDependencies(tree, projectGraph, dependenciesToUpdate) { let numDependenciesToUpdate = Object.keys(dependenciesToUpdate).length; if (numDependenciesToUpdate === 0) { return []; } const logMessages = []; for (const manifestToUpdate of this.manifestsToUpdate) { (0, devkit_1.updateJson)(tree, manifestToUpdate.manifestPath, (json) => { const dependencyTypes = [ 'dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies', ]; for (const depType of dependencyTypes) { if (json[depType]) { for (const [dep, version] of Object.entries(dependenciesToUpdate)) { // Resolve the package name from the project graph metadata, as it may not match the project name const packageName = projectGraph.nodes[dep].data.metadata?.js?.packageName; if (!packageName) { throw new Error(`Unable to determine the package name for project "${dep}" from the project graph metadata, please ensure that the "@nx/js" plugin is installed and the project graph has been built. If the issue persists, please report this issue on https://github.com/nrwl/nx/issues`); } const currentVersion = json[depType][packageName]; if (currentVersion) { // Check if the local dependency protocol should be preserved or not if (manifestToUpdate.preserveLocalDependencyProtocols && this.isLocalDependencyProtocol(currentVersion)) { // Reduce the count appropriately to avoid confusing user-facing logs numDependenciesToUpdate--; continue; } json[depType][packageName] = version; } } } } return json; }); // If we ignored local dependecy protocols, then we could have dynamically ended up with zero here and we should not log anything related to dependencies if (numDependenciesToUpdate === 0) { return []; } const depText = numDependenciesToUpdate === 1 ? 'dependency' : 'dependencies'; logMessages.push(`✍️ Updated ${numDependenciesToUpdate} ${depText} in manifest: ${manifestToUpdate.manifestPath}`); } return logMessages; } // NOTE: The TODOs were carried over from the original implementation, they are not yet implemented isLocalDependencyProtocol(versionSpecifier) { const localPackageProtocols = [ 'file:', // all package managers 'workspace:', // not npm // TODO: Support portal protocol at the project graph level before enabling here // 'portal:', // modern yarn only ]; // Not using a supported local protocol if (!localPackageProtocols.some((protocol) => versionSpecifier.startsWith(protocol))) { return false; } // Supported by all package managers if (versionSpecifier.startsWith('file:')) { return true; } // Determine specific package manager in use if (!pm) { pm = (0, devkit_1.detectPackageManager)(); // pmVersion = getPackageManagerVersion(pm); } if (pm === 'npm' && versionSpecifier.startsWith('workspace:')) { throw new Error(`The "workspace:" protocol is not yet supported by npm (https://github.com/npm/rfcs/issues/765). Please ensure you have a valid setup according to your package manager before attempting to release packages.`); } // TODO: Support portal protocol at the project graph level before enabling here // if ( // version.startsWith('portal:') && // (pm !== 'yarn' || lt(pmVersion, '2.0.0')) // ) { // throw new Error( // `The "portal:" protocol is only supported by yarn@2.0.0 and above. Please ensure you have a valid setup according to your package manager before attempting to release packages.` // ); // } return true; } } exports.default = JsVersionActions;