Skip to content

Commit

Permalink
fix(core): nx list should work as expected in encapsulated repo (#15200)
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Feb 24, 2023
1 parent 6b0b30e commit 8a58cdd
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 189 deletions.
50 changes: 36 additions & 14 deletions e2e/nx-misc/src/encapsulated.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getPublishedVersion,
uniq,
} from '@nrwl/e2e/utils';
import { bold } from 'chalk';

describe('encapsulated nx', () => {
let runEncapsulatedNx: ReturnType<typeof newEncapsulatedNxWorkspace>;
Expand Down Expand Up @@ -36,18 +37,13 @@ describe('encapsulated nx', () => {
})
);

updateJson<NxJsonConfiguration>('nx.json', (json) => ({
...json,
tasksRunnerOptions: {
default: {
...json.tasksRunnerOptions['default'],
options: {
...json.tasksRunnerOptions['default'].options,
cacheableOperations: ['echo'],
},
},
},
}));
updateJson<NxJsonConfiguration>('nx.json', (json) => {
json.tasksRunnerOptions.default.options.cacheableOperations = ['echo'];
json.installation.plugins = {
'@nrwl/nest': getPublishedVersion(),
};
return json;
});

expect(runEncapsulatedNx('echo a')).toContain('Hello from A');

Expand All @@ -66,9 +62,35 @@ describe('encapsulated nx', () => {
});

it('should work with nx report', () => {
expect(runEncapsulatedNx('report')).toMatch(
new RegExp(`nx.*:.*${getPublishedVersion()}`)
const output = runEncapsulatedNx('report');
expect(output).toMatch(new RegExp(`nx.*:.*${getPublishedVersion()}`));
expect(output).toMatch(
new RegExp(`@nrwl/nest.*:.*${getPublishedVersion()}`)
);
expect(output).not.toContain('@nrwl/express');
});

it('should work with nx list', () => {
let output = runEncapsulatedNx('list');
const lines = output.split('\n');
const installedPluginStart = lines.findIndex((l) =>
l.includes('Installed plugins')
);
const installedPluginEnd = lines.findIndex((l) =>
l.includes('Also available')
);
const installedPluginLines = lines.slice(
installedPluginStart + 1,
installedPluginEnd
);

expect(installedPluginLines.some((x) => x.includes(`${bold('nx')}`)));
expect(
installedPluginLines.some((x) => x.includes(`${bold('@nrwl/nest')}`))
);

output = runEncapsulatedNx('list @nrwl/nest');
expect(output).toContain('Capabilities in @nrwl/nest');
});

it('should work with basic generators', () => {
Expand Down
10 changes: 4 additions & 6 deletions packages/nx/src/command-line/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,11 @@ export async function listHandler(args: ListArgs): Promise<void> {
const localPlugins = getLocalWorkspacePlugins(
readProjectsConfigurationFromProjectGraph(projectGraph)
);
const installedPlugins = getInstalledPluginsAndCapabilities(
workspaceRoot,
corePlugins,
communityPlugins
);
const installedPlugins = getInstalledPluginsAndCapabilities(workspaceRoot);

listLocalWorkspacePlugins(localPlugins);
if (localPlugins.size) {
listLocalWorkspacePlugins(localPlugins);
}
listInstalledPlugins(installedPlugins);
listCorePlugins(installedPlugins, corePlugins);
listCommunityPlugins(installedPlugins, communityPlugins);
Expand Down
4 changes: 2 additions & 2 deletions packages/nx/src/daemon/server/handle-process-in-background.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HandlerResult } from './server';
import { workspaceRoot } from '../../utils/workspace-root';
import { serverLogger } from './logger';
import { getNxRequirePaths } from '../../utils/installation-directory';

export async function handleProcessInBackground(payload: {
type: string;
Expand All @@ -10,7 +10,7 @@ export async function handleProcessInBackground(payload: {
let fn;
try {
fn = require(require.resolve(payload.requirePath, {
paths: [workspaceRoot],
paths: getNxRequirePaths(),
})).default;
} catch (e) {
return {
Expand Down
22 changes: 13 additions & 9 deletions packages/nx/src/utils/nx-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ export interface NxPlugin {
// executing resolution mulitple times.
let nxPluginCache: Map<string, NxPlugin> = new Map();

function loadNxPlugin(moduleName: string, paths: string[], root: string) {
export function loadNxPlugin(
moduleName: string,
paths: string[],
root: string
) {
let pluginModule = nxPluginCache.get(moduleName);
if (pluginModule) {
return pluginModule;
}

let pluginPath: string;
try {
pluginPath = require.resolve(moduleName, {
Expand Down Expand Up @@ -80,7 +89,7 @@ function loadNxPlugin(moduleName: string, paths: string[], root: string) {
: { name: path.basename(pluginPath) }; // use the name of the file we point to
const plugin = require(pluginPath) as NxPlugin;
plugin.name = name;

nxPluginCache.set(moduleName, plugin);
return plugin;
}

Expand All @@ -100,12 +109,7 @@ export function loadNxPlugins(

plugins ??= [];
for (const plugin of plugins) {
let pluginModule = nxPluginCache.get(plugin);
if (!pluginModule) {
pluginModule = loadNxPlugin(plugin, paths, root);
nxPluginCache.set(plugin, pluginModule);
}
result.push(pluginModule);
result.push(loadNxPlugin(plugin, paths, root));
}

return result;
Expand Down Expand Up @@ -137,7 +141,7 @@ export function mergePluginTargetsWithNxTargets(

export function readPluginPackageJson(
pluginName: string,
paths = [workspaceRoot]
paths = getNxRequirePaths()
): {
path: string;
json: PackageJson;
Expand Down
5 changes: 3 additions & 2 deletions packages/nx/src/utils/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TargetConfiguration,
} from '../config/workspace-json-project-json';
import { readJsonFile } from './fileutils';
import { getNxRequirePaths } from './installation-directory';
import { workspaceRoot } from './workspace-root';

export type PackageJsonTargetConfiguration = Omit<
Expand Down Expand Up @@ -142,7 +143,7 @@ export function buildTargetFromScript(
*/
export function readModulePackageJsonWithoutFallbacks(
moduleSpecifier: string,
requirePaths = [workspaceRoot]
requirePaths = getNxRequirePaths()
): {
packageJson: PackageJson;
path: string;
Expand Down Expand Up @@ -177,7 +178,7 @@ export function readModulePackageJsonWithoutFallbacks(
*/
export function readModulePackageJson(
moduleSpecifier: string,
requirePaths = [workspaceRoot]
requirePaths = getNxRequirePaths()
): {
packageJson: PackageJson;
path: string;
Expand Down
48 changes: 20 additions & 28 deletions packages/nx/src/utils/plugins/installed-plugins.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as chalk from 'chalk';
import { output } from '../output';
import type { CommunityPlugin, CorePlugin, PluginCapabilities } from './models';
import type { PluginCapabilities } from './models';
import { getPluginCapabilities } from './plugin-capabilities';
import { hasElements } from './shared';
import { readJsonFile } from '../fileutils';
Expand Down Expand Up @@ -66,35 +66,21 @@ function getDependenciesFromNxJson(): string[] {
}

export function getInstalledPluginsAndCapabilities(
workspaceRoot: string,
corePlugins: CorePlugin[],
communityPlugins: CommunityPlugin[] = []
workspaceRoot: string
): Map<string, PluginCapabilities> {
const plugins = new Set([
...corePlugins.map((p) => p.name),
...communityPlugins.map((p) => p.name),
...findInstalledPlugins().map((p) => p.name),
]);
const plugins = findInstalledPlugins().map((p) => p.name);

return new Map(
Array.from(plugins)
.filter((name) => {
try {
// Check for `package.json` existence instead of requiring the module itself
// because malformed entries like `main`, may throw false exceptions.
readModulePackageJson(name, [workspaceRoot]);
return true;
} catch {
return false;
}
})
.sort()
.map<[string, PluginCapabilities]>((name) => [
name,
getPluginCapabilities(workspaceRoot, name),
])
.filter(([, x]) => x && !!(x.generators || x.executors))
);
const result = new Map<string, PluginCapabilities>();
for (const plugin of Array.from(plugins).sort()) {
try {
const capabilities = getPluginCapabilities(workspaceRoot, plugin);
if (capabilities.executors || capabilities.generators) {
result.set(plugin, capabilities);
}
} catch {}
}

return result;
}

export function listInstalledPlugins(
Expand All @@ -110,6 +96,12 @@ export function listInstalledPlugins(
if (hasElements(p.generators)) {
capabilities.push('generators');
}
if (p.projectGraphExtension) {
capabilities.push('graph-extensions');
}
if (p.projectInference) {
capabilities.push('project-inference');
}
bodyLines.push(`${chalk.bold(p.name)} (${capabilities.join()})`);
}

Expand Down
34 changes: 15 additions & 19 deletions packages/nx/src/utils/plugins/local-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { output } from '../output';
import type { PluginCapabilities } from './models';
import { hasElements } from './shared';
import { readJsonFile } from '../fileutils';
import { PackageJson } from '../package-json';
import { PackageJson, readNxMigrateConfig } from '../package-json';
import { ProjectsConfigurations } from '../../config/workspace-json-project-json';
import { join } from 'path';
import { workspaceRoot } from '../workspace-root';
import { existsSync } from 'fs';
import { ExecutorsJson, GeneratorsJson } from '../../config/misc-interfaces';
import { loadNxPlugin } from '../nx-plugin';
import { getNxRequirePaths } from '../installation-directory';
import { getPluginCapabilities } from './plugin-capabilities';

export function getLocalWorkspacePlugins(
projectsConfiguration: ProjectsConfigurations
Expand All @@ -18,25 +21,18 @@ export function getLocalWorkspacePlugins(
const packageJsonPath = join(workspaceRoot, project.root, 'package.json');
if (existsSync(packageJsonPath)) {
const packageJson: PackageJson = readJsonFile(packageJsonPath);
const capabilities: Partial<PluginCapabilities> = {};
const generatorsPath = packageJson.generators ?? packageJson.schematics;
const executorsPath = packageJson.executors ?? packageJson.builders;
if (generatorsPath) {
const file = readJsonFile<GeneratorsJson>(
join(workspaceRoot, project.root, generatorsPath)
);
capabilities.generators = file.generators ?? file.schematics;
}
if (executorsPath) {
const file = readJsonFile<ExecutorsJson>(
join(workspaceRoot, project.root, executorsPath)
);
capabilities.executors = file.executors ?? file.builders;
}
if (capabilities.executors || capabilities.generators) {
const capabilities = getPluginCapabilities(
workspaceRoot,
packageJson.name
);
if (
capabilities.executors ||
capabilities.generators ||
capabilities.projectGraphExtension ||
capabilities.projectInference
) {
plugins.set(packageJson.name, {
executors: capabilities.executors ?? {},
generators: capabilities.generators ?? {},
...capabilities,
name: packageJson.name,
});
}
Expand Down
2 changes: 2 additions & 0 deletions packages/nx/src/utils/plugins/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface PluginCapabilities {
name: string;
executors: { [name: string]: ExecutorsJsonEntry };
generators: { [name: string]: GeneratorsJsonEntry };
projectInference: boolean;
projectGraphExtension: boolean;
}

export interface CorePlugin {
Expand Down
33 changes: 29 additions & 4 deletions packages/nx/src/utils/plugins/plugin-capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import type { PluginCapabilities } from './models';
import { hasElements } from './shared';
import { readJsonFile } from '../fileutils';
import { getPackageManagerCommand } from '../package-manager';
import { readPluginPackageJson } from '../nx-plugin';
import { loadNxPlugin, readPluginPackageJson } from '../nx-plugin';
import { getNxRequirePaths } from '../installation-directory';

function tryGetCollection<T extends object>(
packageJsonPath: string,
Expand All @@ -30,8 +31,15 @@ export function getPluginCapabilities(
pluginName: string
): PluginCapabilities | null {
try {
const { json: packageJson, path: packageJsonPath } =
readPluginPackageJson(pluginName);
const { json: packageJson, path: packageJsonPath } = readPluginPackageJson(
pluginName,
getNxRequirePaths(workspaceRoot)
);
const pluginModule = loadNxPlugin(
pluginName,
getNxRequirePaths(workspaceRoot),
workspaceRoot
);
return {
name: pluginName,
generators:
Expand All @@ -56,6 +64,8 @@ export function getPluginCapabilities(
tryGetCollection(packageJsonPath, packageJson.executors, 'builders') ||
tryGetCollection(packageJsonPath, packageJson.builders, 'executors') ||
tryGetCollection(packageJsonPath, packageJson.builders, 'builders'),
projectGraphExtension: !!pluginModule.processProjectGraph,
projectInference: !!pluginModule.projectFilePatterns,
};
} catch {
return null;
Expand All @@ -80,8 +90,15 @@ export function listPluginCapabilities(pluginName: string) {

const hasBuilders = hasElements(plugin.executors);
const hasGenerators = hasElements(plugin.generators);
const hasProjectGraphExtension = !!plugin.projectGraphExtension;
const hasProjectInference = !!plugin.projectInference;

if (!hasBuilders && !hasGenerators) {
if (
!hasBuilders &&
!hasGenerators &&
!hasProjectGraphExtension &&
!hasProjectInference
) {
output.warn({ title: `No capabilities found in ${pluginName}` });
return;
}
Expand Down Expand Up @@ -111,6 +128,14 @@ export function listPluginCapabilities(pluginName: string) {
);
}

if (hasProjectGraphExtension) {
bodyLines.push(`✔️ Project Graph Extension`);
}

if (hasProjectInference) {
bodyLines.push(`✔️ Project Inference`);
}

output.log({
title: `Capabilities in ${plugin.name}:`,
bodyLines,
Expand Down
Loading

1 comment on commit 8a58cdd

@vercel
Copy link

@vercel vercel bot commented on 8a58cdd Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx.dev
nx-five.vercel.app
nx-dev-nrwl.vercel.app

Please sign in to comment.