@nx/js
Version:
203 lines (202 loc) • 9.96 kB
JavaScript
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;
;