cleanup(core): refactor nx list command to remove unused code and code duplication (#21748)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior <!-- This is the behavior we have today --> the code for the `nx list` command has unused and duplicated code. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> no unused code and code duplication ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes # --------- Co-authored-by: Craigory Coppola <craigorycoppola@gmail.com>
This commit is contained in:
parent
a8dc251cce
commit
aeec5cc31a
@ -1,21 +1,17 @@
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
import { output } from '../../utils/output';
|
||||
import {
|
||||
fetchCorePlugins,
|
||||
getInstalledPluginsAndCapabilities,
|
||||
listCorePlugins,
|
||||
listInstalledPlugins,
|
||||
listPluginCapabilities,
|
||||
} from '../../utils/plugins';
|
||||
import {
|
||||
getLocalWorkspacePlugins,
|
||||
listLocalWorkspacePlugins,
|
||||
} from '../../utils/plugins/local-plugins';
|
||||
import { readNxJson } from '../../config/nx-json';
|
||||
import {
|
||||
createProjectGraphAsync,
|
||||
readProjectsConfigurationFromProjectGraph,
|
||||
} from '../../project-graph/project-graph';
|
||||
import { readNxJson } from '../../config/nx-json';
|
||||
import { output } from '../../utils/output';
|
||||
import {
|
||||
getInstalledPluginsAndCapabilities,
|
||||
getLocalWorkspacePlugins,
|
||||
listAlsoAvailableCorePlugins,
|
||||
listPluginCapabilities,
|
||||
listPlugins,
|
||||
} from '../../utils/plugins';
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
|
||||
export interface ListArgs {
|
||||
/** The name of an installed plugin to query */
|
||||
@ -31,14 +27,13 @@ export interface ListArgs {
|
||||
*
|
||||
*/
|
||||
export async function listHandler(args: ListArgs): Promise<void> {
|
||||
const nxJson = readNxJson();
|
||||
const projectGraph = await createProjectGraphAsync({ exitOnError: true });
|
||||
const projects = readProjectsConfigurationFromProjectGraph(projectGraph);
|
||||
|
||||
if (args.plugin) {
|
||||
await listPluginCapabilities(args.plugin, projects.projects);
|
||||
} else {
|
||||
const corePlugins = fetchCorePlugins();
|
||||
const nxJson = readNxJson();
|
||||
|
||||
const localPlugins = await getLocalWorkspacePlugins(projects, nxJson);
|
||||
const installedPlugins = await getInstalledPluginsAndCapabilities(
|
||||
@ -47,22 +42,20 @@ export async function listHandler(args: ListArgs): Promise<void> {
|
||||
);
|
||||
|
||||
if (localPlugins.size) {
|
||||
listLocalWorkspacePlugins(localPlugins);
|
||||
listPlugins(localPlugins, 'Local workspace plugins:');
|
||||
}
|
||||
listInstalledPlugins(installedPlugins);
|
||||
listCorePlugins(installedPlugins, corePlugins);
|
||||
listPlugins(installedPlugins, 'Installed plugins:');
|
||||
listAlsoAvailableCorePlugins(installedPlugins);
|
||||
|
||||
output.note({
|
||||
title: 'Community Plugins',
|
||||
bodyLines: [
|
||||
'Looking for a technology / framework not listed above?',
|
||||
'There are many excellent plugins maintained by the Nx community.',
|
||||
'Search for the one you need here: https://nx.dev/plugins/registry.',
|
||||
'Search for the one you need here: https://nx.dev/plugin-registry.',
|
||||
],
|
||||
});
|
||||
|
||||
output.note({
|
||||
title: `Use "nx list [plugin]" to find out more`,
|
||||
});
|
||||
output.note({ title: `Use "nx list [plugin]" to find out more` });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
import { get } from 'https';
|
||||
import type { CommunityPlugin } from './models';
|
||||
|
||||
const COMMUNITY_PLUGINS_JSON_URL =
|
||||
'https://raw.githubusercontent.com/nrwl/nx/master/community/approved-plugins.json';
|
||||
|
||||
export async function fetchCommunityPlugins(): Promise<CommunityPlugin[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = get(COMMUNITY_PLUGINS_JSON_URL, (res) => {
|
||||
if (res.statusCode < 200 || res.statusCode >= 300) {
|
||||
reject(new Error(`Request failed with status code ${res.statusCode}`));
|
||||
}
|
||||
|
||||
const data = [];
|
||||
res.on('data', (chunk) => {
|
||||
data.push(chunk);
|
||||
});
|
||||
res.on('end', () => {
|
||||
try {
|
||||
resolve(JSON.parse(Buffer.concat(data).toString('utf-8')));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
@ -1,122 +1,112 @@
|
||||
import * as chalk from 'chalk';
|
||||
import { output } from '../output';
|
||||
import type { CorePlugin, PluginCapabilities } from './models';
|
||||
|
||||
export function fetchCorePlugins(): CorePlugin[] {
|
||||
return [
|
||||
{
|
||||
name: '@nx/angular',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/cypress',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/detox',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/esbuild',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/expo',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/express',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/jest',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/js',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/eslint',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/nest',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/next',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/node',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/nuxt',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: 'nx',
|
||||
capabilities: 'executors',
|
||||
},
|
||||
{
|
||||
name: '@nx/plugin',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/react',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/react-native',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/remix',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/rollup',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/storybook',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/vite',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/web',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/webpack',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/workspace',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
];
|
||||
export interface CorePlugin {
|
||||
name: string;
|
||||
capabilities: 'executors' | 'generators' | 'executors,generators' | 'graph';
|
||||
link?: string;
|
||||
}
|
||||
|
||||
export function listCorePlugins(
|
||||
installedPlugins: Map<string, PluginCapabilities>,
|
||||
corePlugins: CorePlugin[]
|
||||
): void {
|
||||
const alsoAvailable = corePlugins.filter(
|
||||
(p) => !installedPlugins.has(p.name)
|
||||
);
|
||||
|
||||
if (alsoAvailable.length) {
|
||||
output.log({
|
||||
title: `Also available:`,
|
||||
bodyLines: alsoAvailable.map((p) => {
|
||||
return `${chalk.bold(p.name)} (${p.capabilities})`;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
export const CORE_PLUGINS: CorePlugin[] = [
|
||||
{
|
||||
name: '@nx/angular',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/cypress',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/detox',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/esbuild',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/expo',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/express',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/gradle',
|
||||
capabilities: 'graph',
|
||||
},
|
||||
{
|
||||
name: '@nx/jest',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/js',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/eslint',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/nest',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/next',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/node',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/nuxt',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: 'nx',
|
||||
capabilities: 'executors',
|
||||
},
|
||||
{
|
||||
name: '@nx/plugin',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/react',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/react-native',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/remix',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/rollup',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/storybook',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/vite',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/vue',
|
||||
capabilities: 'generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/web',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/webpack',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
{
|
||||
name: '@nx/workspace',
|
||||
capabilities: 'executors,generators',
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
export { fetchCommunityPlugins } from './community-plugins';
|
||||
export { fetchCorePlugins, listCorePlugins } from './core-plugins';
|
||||
export { getInstalledPluginsAndCapabilities } from './installed-plugins';
|
||||
export { getLocalWorkspacePlugins } from './local-plugins';
|
||||
export {
|
||||
getInstalledPluginsAndCapabilities,
|
||||
listInstalledPlugins,
|
||||
} from './installed-plugins';
|
||||
export {
|
||||
getPluginCapabilities,
|
||||
listPlugins,
|
||||
listAlsoAvailableCorePlugins,
|
||||
listPluginCapabilities,
|
||||
} from './plugin-capabilities';
|
||||
} from './output';
|
||||
export { getPluginCapabilities } from './plugin-capabilities';
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import * as chalk from 'chalk';
|
||||
import { output } from '../output';
|
||||
import type { PluginCapabilities } from './models';
|
||||
import { getPluginCapabilities } from './plugin-capabilities';
|
||||
import { hasElements } from './shared';
|
||||
import { readJsonFile } from '../fileutils';
|
||||
import { PackageJson, readModulePackageJson } from '../package-json';
|
||||
import { workspaceRoot } from '../workspace-root';
|
||||
import { join } from 'path';
|
||||
import { readNxJson } from '../../config/nx-json';
|
||||
import { getNxRequirePaths } from '../installation-directory';
|
||||
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
import { readJsonFile } from '../fileutils';
|
||||
import { getNxRequirePaths } from '../installation-directory';
|
||||
import { PackageJson, readModulePackageJson } from '../package-json';
|
||||
import { workspaceRoot } from '../workspace-root';
|
||||
import {
|
||||
PluginCapabilities,
|
||||
getPluginCapabilities,
|
||||
} from './plugin-capabilities';
|
||||
|
||||
export function findInstalledPlugins(): PackageJson[] {
|
||||
const packageJsonDeps = getDependenciesFromPackageJson();
|
||||
@ -92,31 +91,3 @@ export async function getInstalledPluginsAndCapabilities(
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function listInstalledPlugins(
|
||||
installedPlugins: Map<string, PluginCapabilities>
|
||||
) {
|
||||
const bodyLines: string[] = [];
|
||||
|
||||
for (const [, p] of installedPlugins) {
|
||||
const capabilities = [];
|
||||
if (hasElements(p.executors)) {
|
||||
capabilities.push('executors');
|
||||
}
|
||||
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()})`);
|
||||
}
|
||||
|
||||
output.log({
|
||||
title: `Installed plugins:`,
|
||||
bodyLines: bodyLines,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import * as chalk from 'chalk';
|
||||
import { output } from '../output';
|
||||
import type { PluginCapabilities } from './models';
|
||||
import { hasElements } from './shared';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { NxJsonConfiguration } from '../../config/nx-json';
|
||||
import { ProjectsConfigurations } from '../../config/workspace-json-project-json';
|
||||
import { readJsonFile } from '../fileutils';
|
||||
import { PackageJson } 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 { getPluginCapabilities } from './plugin-capabilities';
|
||||
import { NxJsonConfiguration, readNxJson } from '../../config/nx-json';
|
||||
import {
|
||||
PluginCapabilities,
|
||||
getPluginCapabilities,
|
||||
} from './plugin-capabilities';
|
||||
|
||||
export async function getLocalWorkspacePlugins(
|
||||
projectsConfiguration: ProjectsConfigurations,
|
||||
@ -45,31 +44,3 @@ export async function getLocalWorkspacePlugins(
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
export function listLocalWorkspacePlugins(
|
||||
installedPlugins: Map<string, PluginCapabilities>
|
||||
) {
|
||||
const bodyLines: string[] = [];
|
||||
|
||||
for (const [, p] of installedPlugins) {
|
||||
const capabilities = [];
|
||||
if (hasElements(p.executors)) {
|
||||
capabilities.push('executors');
|
||||
}
|
||||
if (hasElements(p.generators)) {
|
||||
capabilities.push('generators');
|
||||
}
|
||||
if (p.projectGraphExtension) {
|
||||
capabilities.push('graph-extension');
|
||||
}
|
||||
if (p.projectInference) {
|
||||
capabilities.push('project-inference');
|
||||
}
|
||||
bodyLines.push(`${chalk.bold(p.name)} (${capabilities.join()})`);
|
||||
}
|
||||
|
||||
output.log({
|
||||
title: `Local workspace plugins:`,
|
||||
bodyLines: bodyLines,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
import {
|
||||
ExecutorsJsonEntry,
|
||||
GeneratorsJsonEntry,
|
||||
} from '../../config/misc-interfaces';
|
||||
|
||||
export interface PluginCapabilities {
|
||||
name: string;
|
||||
executors?: { [name: string]: ExecutorsJsonEntry };
|
||||
generators?: { [name: string]: GeneratorsJsonEntry };
|
||||
projectInference?: boolean;
|
||||
projectGraphExtension?: boolean;
|
||||
}
|
||||
|
||||
export interface CorePlugin {
|
||||
name: string;
|
||||
capabilities: 'executors' | 'generators' | 'executors,generators';
|
||||
link?: string;
|
||||
}
|
||||
|
||||
export interface CommunityPlugin {
|
||||
name: string;
|
||||
url: string;
|
||||
description: string;
|
||||
}
|
||||
142
packages/nx/src/utils/plugins/output.ts
Normal file
142
packages/nx/src/utils/plugins/output.ts
Normal file
@ -0,0 +1,142 @@
|
||||
import * as chalk from 'chalk';
|
||||
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
import { output } from '../output';
|
||||
import { getPackageManagerCommand } from '../package-manager';
|
||||
import { workspaceRoot } from '../workspace-root';
|
||||
import { CORE_PLUGINS } from './core-plugins';
|
||||
import {
|
||||
PluginCapabilities,
|
||||
getPluginCapabilities,
|
||||
} from './plugin-capabilities';
|
||||
import { readModulePackageJson } from '../package-json';
|
||||
|
||||
export function listPlugins(
|
||||
plugins: Map<string, PluginCapabilities>,
|
||||
title: string
|
||||
) {
|
||||
readModulePackageJson;
|
||||
const bodyLines: string[] = [];
|
||||
|
||||
for (const [, p] of plugins) {
|
||||
const capabilities = [];
|
||||
if (hasElements(p.executors)) {
|
||||
capabilities.push('executors');
|
||||
}
|
||||
if (hasElements(p.generators)) {
|
||||
capabilities.push('generators');
|
||||
}
|
||||
if (p.projectGraphExtension) {
|
||||
capabilities.push('graph-extension');
|
||||
}
|
||||
if (p.projectInference) {
|
||||
capabilities.push('project-inference');
|
||||
}
|
||||
bodyLines.push(`${chalk.bold(p.name)} (${capabilities.join()})`);
|
||||
}
|
||||
|
||||
output.log({
|
||||
title: title,
|
||||
bodyLines: bodyLines,
|
||||
});
|
||||
}
|
||||
|
||||
export function listAlsoAvailableCorePlugins(
|
||||
installedPlugins: Map<string, PluginCapabilities>
|
||||
): void {
|
||||
const alsoAvailable = CORE_PLUGINS.filter(
|
||||
(p) => !installedPlugins.has(p.name)
|
||||
);
|
||||
|
||||
if (alsoAvailable.length) {
|
||||
output.log({
|
||||
title: `Also available:`,
|
||||
bodyLines: alsoAvailable.map((p) => {
|
||||
return `${chalk.bold(p.name)} (${p.capabilities})`;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function listPluginCapabilities(
|
||||
pluginName: string,
|
||||
projects: Record<string, ProjectConfiguration>
|
||||
) {
|
||||
const plugin = await getPluginCapabilities(
|
||||
workspaceRoot,
|
||||
pluginName,
|
||||
projects
|
||||
);
|
||||
|
||||
if (!plugin) {
|
||||
const pmc = getPackageManagerCommand();
|
||||
output.note({
|
||||
title: `${pluginName} is not currently installed`,
|
||||
bodyLines: [
|
||||
`Use "${pmc.addDev} ${pluginName}" to install the plugin.`,
|
||||
`After that, use "${pmc.exec} nx g ${pluginName}:init" to add the required peer deps and initialize the plugin.`,
|
||||
],
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const hasBuilders = hasElements(plugin.executors);
|
||||
const hasGenerators = hasElements(plugin.generators);
|
||||
const hasProjectGraphExtension = !!plugin.projectGraphExtension;
|
||||
const hasProjectInference = !!plugin.projectInference;
|
||||
|
||||
if (
|
||||
!hasBuilders &&
|
||||
!hasGenerators &&
|
||||
!hasProjectGraphExtension &&
|
||||
!hasProjectInference
|
||||
) {
|
||||
output.warn({ title: `No capabilities found in ${pluginName}` });
|
||||
return;
|
||||
}
|
||||
|
||||
const bodyLines = [];
|
||||
|
||||
if (hasGenerators) {
|
||||
bodyLines.push(chalk.bold(chalk.green('GENERATORS')));
|
||||
bodyLines.push('');
|
||||
bodyLines.push(
|
||||
...Object.keys(plugin.generators).map(
|
||||
(name) => `${chalk.bold(name)} : ${plugin.generators[name].description}`
|
||||
)
|
||||
);
|
||||
if (hasBuilders) {
|
||||
bodyLines.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBuilders) {
|
||||
bodyLines.push(chalk.bold(chalk.green('EXECUTORS/BUILDERS')));
|
||||
bodyLines.push('');
|
||||
bodyLines.push(
|
||||
...Object.keys(plugin.executors).map((name) => {
|
||||
const definition = plugin.executors[name];
|
||||
return typeof definition === 'string'
|
||||
? chalk.bold(name)
|
||||
: `${chalk.bold(name)} : ${definition.description}`;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (hasProjectGraphExtension) {
|
||||
bodyLines.push(`✔️ Project Graph Extension`);
|
||||
}
|
||||
|
||||
if (hasProjectInference) {
|
||||
bodyLines.push(`✔️ Project Inference`);
|
||||
}
|
||||
|
||||
output.log({
|
||||
title: `Capabilities in ${plugin.name}:`,
|
||||
bodyLines,
|
||||
});
|
||||
}
|
||||
|
||||
function hasElements(obj: any): boolean {
|
||||
return obj && Object.values(obj).length > 0;
|
||||
}
|
||||
@ -1,19 +1,22 @@
|
||||
import * as chalk from 'chalk';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
import {
|
||||
ExecutorsJsonEntry,
|
||||
GeneratorsJsonEntry,
|
||||
} from '../../config/misc-interfaces';
|
||||
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
import { NxPlugin, readPluginPackageJson } from '../../project-graph/plugins';
|
||||
import { loadNxPlugin } from '../../project-graph/plugins/loader';
|
||||
import { readJsonFile } from '../fileutils';
|
||||
import { getNxRequirePaths } from '../installation-directory';
|
||||
import { output } from '../output';
|
||||
import { NxPlugin, readPluginPackageJson } from '../../project-graph/plugins';
|
||||
import { loadNxPlugin } from '../../project-graph/plugins/loader';
|
||||
import { PackageJson } from '../package-json';
|
||||
import { getPackageManagerCommand } from '../package-manager';
|
||||
import { workspaceRoot } from '../workspace-root';
|
||||
import { hasElements } from './shared';
|
||||
|
||||
import type { PluginCapabilities } from './models';
|
||||
import type { ExecutorsJsonEntry } from '../../config/misc-interfaces';
|
||||
export interface PluginCapabilities {
|
||||
name: string;
|
||||
executors?: { [name: string]: ExecutorsJsonEntry };
|
||||
generators?: { [name: string]: GeneratorsJsonEntry };
|
||||
projectInference?: boolean;
|
||||
projectGraphExtension?: boolean;
|
||||
}
|
||||
|
||||
function tryGetCollection<T extends object>(
|
||||
packageJsonPath: string,
|
||||
@ -121,145 +124,3 @@ async function tryGetModule(
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function listPluginCapabilities(
|
||||
pluginName: string,
|
||||
projects: Record<string, ProjectConfiguration>
|
||||
) {
|
||||
const plugin = await getPluginCapabilities(
|
||||
workspaceRoot,
|
||||
pluginName,
|
||||
projects
|
||||
);
|
||||
|
||||
if (!plugin) {
|
||||
const pmc = getPackageManagerCommand();
|
||||
output.note({
|
||||
title: `${pluginName} is not currently installed`,
|
||||
bodyLines: [
|
||||
`Use "${pmc.addDev} ${pluginName}" to install the plugin.`,
|
||||
`After that, use "${pmc.exec} nx g ${pluginName}:init" to add the required peer deps and initialize the plugin.`,
|
||||
],
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const hasBuilders = hasElements(plugin.executors);
|
||||
const hasGenerators = hasElements(plugin.generators);
|
||||
const hasProjectGraphExtension = !!plugin.projectGraphExtension;
|
||||
const hasProjectInference = !!plugin.projectInference;
|
||||
|
||||
if (
|
||||
!hasBuilders &&
|
||||
!hasGenerators &&
|
||||
!hasProjectGraphExtension &&
|
||||
!hasProjectInference
|
||||
) {
|
||||
output.warn({ title: `No capabilities found in ${pluginName}` });
|
||||
return;
|
||||
}
|
||||
|
||||
const bodyLines = [];
|
||||
|
||||
if (hasGenerators) {
|
||||
bodyLines.push(chalk.bold(chalk.green('GENERATORS')));
|
||||
bodyLines.push('');
|
||||
bodyLines.push(
|
||||
...Object.keys(plugin.generators).map(
|
||||
(name) => `${chalk.bold(name)} : ${plugin.generators[name].description}`
|
||||
)
|
||||
);
|
||||
if (hasBuilders) {
|
||||
bodyLines.push('');
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBuilders) {
|
||||
bodyLines.push(chalk.bold(chalk.green('EXECUTORS/BUILDERS')));
|
||||
bodyLines.push('');
|
||||
bodyLines.push(
|
||||
...Object.keys(plugin.executors).map(
|
||||
(name) =>
|
||||
`${chalk.bold(name)} : ${resolveExecutorDescription(
|
||||
pluginName,
|
||||
plugin.executors[name],
|
||||
projects
|
||||
)}`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (hasProjectGraphExtension) {
|
||||
bodyLines.push(`✔️ Project Graph Extension`);
|
||||
}
|
||||
|
||||
if (hasProjectInference) {
|
||||
bodyLines.push(`✔️ Project Inference`);
|
||||
}
|
||||
|
||||
output.log({
|
||||
title: `Capabilities in ${plugin.name}:`,
|
||||
bodyLines,
|
||||
});
|
||||
}
|
||||
|
||||
function resolveExecutorDescription(
|
||||
pluginName: string,
|
||||
executorJsonEntry: ExecutorsJsonEntry,
|
||||
projects: Record<string, ProjectConfiguration>,
|
||||
requirePaths = getNxRequirePaths(workspaceRoot)
|
||||
) {
|
||||
try {
|
||||
if (typeof executorJsonEntry === 'string') {
|
||||
// it points to another executor, resolve it
|
||||
const [pkgName, executor] = executorJsonEntry.split(':');
|
||||
// read the package.json of the parent plugin
|
||||
const { path: packageJsonPath } = readPluginPackageJson(
|
||||
pluginName,
|
||||
projects,
|
||||
requirePaths
|
||||
);
|
||||
// accumulate the require paths to resolve nested packages
|
||||
const cummulativeRequirePaths = [
|
||||
...requirePaths,
|
||||
dirname(packageJsonPath),
|
||||
];
|
||||
const collection = loadExecutorsCollection(
|
||||
pkgName,
|
||||
projects,
|
||||
cummulativeRequirePaths
|
||||
);
|
||||
|
||||
return resolveExecutorDescription(
|
||||
pkgName,
|
||||
collection[executor],
|
||||
projects,
|
||||
cummulativeRequirePaths
|
||||
);
|
||||
}
|
||||
|
||||
return executorJsonEntry.description;
|
||||
} catch {
|
||||
return 'No description available';
|
||||
}
|
||||
}
|
||||
|
||||
function loadExecutorsCollection(
|
||||
pluginName: string,
|
||||
projects: Record<string, ProjectConfiguration>,
|
||||
requirePaths: string[]
|
||||
): { [name: string]: ExecutorsJsonEntry } {
|
||||
const { json: packageJson, path: packageJsonPath } = readPluginPackageJson(
|
||||
pluginName,
|
||||
projects,
|
||||
requirePaths
|
||||
);
|
||||
|
||||
return {
|
||||
...tryGetCollection(packageJsonPath, packageJson.builders, 'builders'),
|
||||
...tryGetCollection(packageJsonPath, packageJson.executors, 'builders'),
|
||||
...tryGetCollection(packageJsonPath, packageJson.builders, 'executors'),
|
||||
...tryGetCollection(packageJsonPath, packageJson.executors, 'executors'),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
// Lifted in part from https://github.com/nrwl/angular-console
|
||||
|
||||
export function hasElements(obj: any): boolean {
|
||||
return obj && Object.values(obj).length > 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user