@harves/nx-node-esm-plugin
Version:
Node executor including ESM module resolution for buildable libraries within Nx workspaces.
274 lines • 11.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateDependenciesFromTaskGraph = exports.calculateProjectDependencies = void 0;
const path_1 = require("path");
const devkit_1 = require("@nx/devkit");
const fileutils_1 = require("nx/src/utils/fileutils");
/**
*
* @param target
* @param node
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L23C1-L29C2
*/
function isBuildable(target, node) {
return (node.data.targets &&
node.data.targets[target] &&
node.data.targets[target].executor !== '');
}
/**
*
* @param projGraph
* @param root
* @param projectName
* @param targetName
* @param configurationName
* @param shallow
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L73C1-L164C2
*/
function calculateProjectDependencies(projGraph, root, projectName, targetName, configurationName, shallow) {
const target = projGraph.nodes[projectName];
// gather the library dependencies
const nonBuildableDependencies = [];
const topLevelDependencies = [];
const collectedDeps = collectDependencies(projectName, projGraph, [], shallow);
const missing = collectedDeps.reduce((missing, { name: dep }) => {
const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
if (!depNode) {
missing = missing || [];
missing.push(dep);
}
return missing;
}, null);
if (missing) {
throw new Error(`Unable to find ${missing.join(', ')} in project graph.`);
}
const dependencies = collectedDeps
.map(({ name: dep, isTopLevel }) => {
let project = null;
const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
if (depNode.type === 'lib') {
if (isBuildable(targetName, depNode)) {
const libPackageJsonPath = (0, path_1.join)(root, depNode.data.root, 'package.json');
project = {
name: (0, fileutils_1.fileExists)(libPackageJsonPath)
? (0, fileutils_1.readJsonFile)(libPackageJsonPath).name // i.e. @workspace/mylib
: dep,
target: targetName,
outputs: (0, devkit_1.getOutputsForTargetAndConfiguration)({
project: projectName,
target: targetName,
configuration: configurationName,
}, {}, depNode),
node: depNode,
};
}
else {
nonBuildableDependencies.push(dep);
}
}
else if (depNode.type === 'npm') {
project = {
name: depNode.data.packageName,
target: targetName,
outputs: [],
node: depNode,
};
}
if (project && isTopLevel) {
topLevelDependencies.push(project);
}
return project;
})
.filter((x) => !!x);
dependencies.sort((a, b) => (a.name > b.name ? 1 : b.name > a.name ? -1 : 0));
return {
target,
dependencies,
nonBuildableDependencies,
topLevelDependencies,
};
}
exports.calculateProjectDependencies = calculateProjectDependencies;
/**
*
* @param project
* @param projGraph
* @param acc
* @param shallow
* @param areTopLevelDeps
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L166C1-L194C2
*/
function collectDependencies(project, projGraph, acc, shallow, areTopLevelDeps = true) {
(projGraph.dependencies[project] || []).forEach((dependency) => {
const existingEntry = acc.find((dep) => dep.name === dependency.target);
if (!existingEntry) {
// Temporary skip this. Currently the set of external nodes is built from package.json, not lock file.
// As a result, some nodes might be missing. This should not cause any issues, we can just skip them.
if (dependency.target.startsWith('npm:') &&
!projGraph.externalNodes[dependency.target])
return;
acc.push({ name: dependency.target, isTopLevel: areTopLevelDeps });
const isInternalTarget = projGraph.nodes[dependency.target];
if (!shallow && isInternalTarget) {
collectDependencies(dependency.target, projGraph, acc, shallow, false);
}
}
else if (areTopLevelDeps && !existingEntry.isTopLevel) {
existingEntry.isTopLevel = true;
}
});
return acc;
}
/**
*
* @param taskGraph
* @param projectGraph
* @param root
* @param projectName
* @param targetName
* @param configurationName
* @param shallow
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L223C1-L314C2
*/
function calculateDependenciesFromTaskGraph(taskGraph, projectGraph, root, projectName, targetName, configurationName, shallow) {
var _a;
const target = projectGraph.nodes[projectName];
const nonBuildableDependencies = [];
const topLevelDependencies = [];
const dependentTasks = collectDependentTasks(projectName, `${projectName}:${targetName}${configurationName ? `:${configurationName}` : ''}`, taskGraph, projectGraph, shallow);
const npmDependencies = collectNpmDependencies(projectName, projectGraph, !shallow ? dependentTasks : undefined);
const dependencies = [];
for (const [taskName, { target, isTopLevel }] of dependentTasks) {
let project = null;
const depTask = taskGraph.tasks[taskName];
const depProjectNode = (_a = projectGraph.nodes) === null || _a === void 0 ? void 0 : _a[depTask.target.project];
if ((depProjectNode === null || depProjectNode === void 0 ? void 0 : depProjectNode.type) !== 'lib') {
continue;
}
const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)(depTask.target, depTask.overrides, depProjectNode);
if (outputs.length === 0) {
nonBuildableDependencies.push(depTask.target.project);
continue;
}
const libPackageJsonPath = (0, path_1.join)(root, depProjectNode.data.root, 'package.json');
project = {
name: (0, fileutils_1.fileExists)(libPackageJsonPath)
? (0, fileutils_1.readJsonFile)(libPackageJsonPath).name // i.e. @workspace/mylib
: depTask.target.project,
target,
outputs,
node: depProjectNode,
};
if (isTopLevel) {
topLevelDependencies.push(project);
}
dependencies.push(project);
}
for (const { project, isTopLevel } of npmDependencies) {
if (isTopLevel) {
topLevelDependencies.push(project);
}
dependencies.push(project);
}
dependencies.sort((a, b) => (a.name > b.name ? 1 : b.name > a.name ? -1 : 0));
return {
target,
dependencies,
nonBuildableDependencies,
topLevelDependencies,
};
}
exports.calculateDependenciesFromTaskGraph = calculateDependenciesFromTaskGraph;
/**
*
* @param projectName
* @param projectGraph
* @param dependentTasks
* @param collectedPackages
* @param isTopLevel
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L316C1-L366C2
*/
function collectNpmDependencies(projectName, projectGraph, dependentTasks, collectedPackages = new Set(), isTopLevel = true) {
const dependencies = projectGraph.dependencies[projectName]
.map((dep) => {
var _a, _b, _c;
const projectNode = (_b = (_a = projectGraph.nodes) === null || _a === void 0 ? void 0 : _a[dep.target]) !== null && _b !== void 0 ? _b : (_c = projectGraph.externalNodes) === null || _c === void 0 ? void 0 : _c[dep.target];
if ((projectNode === null || projectNode === void 0 ? void 0 : projectNode.type) !== 'npm' ||
collectedPackages.has(projectNode.data.packageName)) {
return null;
}
const project = {
name: projectNode.data.packageName,
target: dep.target,
outputs: [],
node: projectNode,
};
collectedPackages.add(project.name);
return { project, isTopLevel };
})
.filter((x) => !!x);
if (dependentTasks === null || dependentTasks === void 0 ? void 0 : dependentTasks.size) {
for (const [, { project: projectName }] of dependentTasks) {
dependencies.push(...collectNpmDependencies(projectName, projectGraph, undefined, collectedPackages, false));
}
}
return dependencies;
}
/**
*
* @param project
* @param task
* @param taskGraph
* @param projectGraph
* @param shallow
* @param areTopLevelDeps
* @param dependentTasks
* @returns
*
* @see https://github.com/nrwl/nx/blob/7f11a1d7d3f2e8a28fef50cdbbb6c4bfc25d6cf7/packages/js/src/utils/buildable-libs-utils.ts#L368-L410
*/
function collectDependentTasks(project, task, taskGraph, projectGraph, shallow, areTopLevelDeps = true, dependentTasks = new Map()) {
const _task = (0, devkit_1.parseTargetString)(task, projectGraph);
let depTasks = taskGraph.dependencies[task];
if (depTasks === undefined) {
/* if direct lookup `taskGraph.dependencies[task]` fails
* we match on project:target (excluding environment) */
const _depTasks = Object.entries(taskGraph.dependencies).find(([t, _deps]) => {
const _t = (0, devkit_1.parseTargetString)(t, projectGraph);
// console.log(' *', _t, (_t.project === _task.project && _t.target === _task.target));
return _t.project === _task.project && _t.target === _task.target;
});
depTasks = _depTasks === null || _depTasks === void 0 ? void 0 : _depTasks[1];
}
for (const depTask of depTasks !== null && depTasks !== void 0 ? depTasks : []) {
if (dependentTasks.has(depTask)) {
if (!dependentTasks.get(depTask).isTopLevel && areTopLevelDeps) {
dependentTasks.get(depTask).isTopLevel = true;
}
continue;
}
const { project: depTaskProject, target: depTaskTarget } = (0, devkit_1.parseTargetString)(depTask, projectGraph);
if (depTaskProject !== project) {
dependentTasks.set(depTask, {
project: depTaskProject,
target: depTaskTarget,
isTopLevel: areTopLevelDeps,
});
}
if (!shallow) {
collectDependentTasks(depTaskProject, depTask, taskGraph, projectGraph, shallow, depTaskProject === project && areTopLevelDeps, dependentTasks);
}
}
return dependentTasks;
}
//# sourceMappingURL=buildable-libs-utils.js.map