From 341cc6bdba7b9780db2e96f3566298eba1aa0477 Mon Sep 17 00:00:00 2001 From: Tasos Bekos Date: Thu, 24 Sep 2020 21:16:57 +0300 Subject: [PATCH] fix(repo): lookup for installed plugins in `package.json` In addition, we refactor the plugin capabilities and installed plugin methods to avoid references to `node_modules`. --- packages/workspace/src/command-line/list.ts | 4 +- packages/workspace/src/utils/plugins/index.ts | 2 +- .../src/utils/plugins/installed-plugins.ts | 58 +++++++------------ .../src/utils/plugins/plugin-capabilities.ts | 25 +++++--- 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/packages/workspace/src/command-line/list.ts b/packages/workspace/src/command-line/list.ts index 7012c03d501a9..4af88ac11a7a6 100644 --- a/packages/workspace/src/command-line/list.ts +++ b/packages/workspace/src/command-line/list.ts @@ -4,7 +4,7 @@ import { output } from '../utils/output'; import { fetchCommunityPlugins, fetchCorePlugins, - getInstalledPluginsFromNodeModules, + getInstalledPluginsFromPackageJson, listCommunityPlugins, listCorePlugins, listInstalledPlugins, @@ -43,7 +43,7 @@ async function listHandler(args: YargsListArgs) { } else { const corePlugins = await fetchCorePlugins(); const communityPlugins = await fetchCommunityPlugins(); - const installedPlugins = getInstalledPluginsFromNodeModules( + const installedPlugins = getInstalledPluginsFromPackageJson( appRootPath, corePlugins, communityPlugins diff --git a/packages/workspace/src/utils/plugins/index.ts b/packages/workspace/src/utils/plugins/index.ts index 007409e5443a7..9ac357e92d22c 100644 --- a/packages/workspace/src/utils/plugins/index.ts +++ b/packages/workspace/src/utils/plugins/index.ts @@ -4,7 +4,7 @@ export { } from './community-plugins'; export { fetchCorePlugins, listCorePlugins } from './core-plugins'; export { - getInstalledPluginsFromNodeModules, + getInstalledPluginsFromPackageJson, listInstalledPlugins, } from './installed-plugins'; export { diff --git a/packages/workspace/src/utils/plugins/installed-plugins.ts b/packages/workspace/src/utils/plugins/installed-plugins.ts index 35690c04e9548..403c480d4b28f 100644 --- a/packages/workspace/src/utils/plugins/installed-plugins.ts +++ b/packages/workspace/src/utils/plugins/installed-plugins.ts @@ -1,50 +1,36 @@ import { terminal } from '@angular-devkit/core'; -import { readdirSync } from 'fs'; -import * as path from 'path'; +import { readJsonFile } from '../fileutils'; import { output } from '../output'; import { CommunityPlugin, CorePlugin, PluginCapabilities } from './models'; import { getPluginCapabilities } from './plugin-capabilities'; import { hasElements } from './shared'; -function getPackagesFromNodeModules( - workspaceRoot: string, - requery: boolean = false -): string[] { - let packageList: string[] = []; - - if (!requery && packageList.length > 0) { - return packageList; - } - - const nodeModulesDir = path.join(workspaceRoot, 'node_modules'); - readdirSync(nodeModulesDir).forEach((npmPackageOrScope) => { - if (npmPackageOrScope.startsWith('@')) { - readdirSync(path.join(nodeModulesDir, npmPackageOrScope)).forEach((p) => { - packageList.push(`${npmPackageOrScope}/${p}`); - }); - } else { - packageList.push(npmPackageOrScope); - } - }); - - return packageList; -} - -export function getInstalledPluginsFromNodeModules( +export function getInstalledPluginsFromPackageJson( workspaceRoot: string, corePlugins: CorePlugin[], communityPlugins: CommunityPlugin[] ): Array { - const corePluginNames = corePlugins.map((p) => p.name); - const communityPluginNames = communityPlugins.map((p) => p.name); - const packages = getPackagesFromNodeModules(workspaceRoot); + const packageJson = readJsonFile(`${workspaceRoot}/package.json`); - return packages - .filter( - (name) => - corePluginNames.indexOf(name) > -1 || - communityPluginNames.indexOf(name) > -1 - ) + const plugins = new Set([ + ...corePlugins.map((p) => p.name), + ...communityPlugins.map((p) => p.name), + ...Object.keys(packageJson.dependencies || {}), + ...Object.keys(packageJson.devDependencies || {}), + ]); + + return [...plugins] + .filter((name) => { + try { + // Check for `package.json` existence instead of requiring the module itself + // because malformed entries like `main`, may throw false exceptions. + require.resolve(`${name}/package.json`, { paths: [workspaceRoot] }); + return true; + } catch { + return false; + } + }) + .sort() .map((name) => getPluginCapabilities(workspaceRoot, name)) .filter((x) => x && !!(x.schematics || x.builders)); } diff --git a/packages/workspace/src/utils/plugins/plugin-capabilities.ts b/packages/workspace/src/utils/plugins/plugin-capabilities.ts index fd688e795d47d..802c465a942aa 100644 --- a/packages/workspace/src/utils/plugins/plugin-capabilities.ts +++ b/packages/workspace/src/utils/plugins/plugin-capabilities.ts @@ -1,5 +1,4 @@ import { terminal } from '@angular-devkit/core'; -import * as path from 'path'; import { appRootPath } from '../app-root'; import { detectPackageManager } from '../detect-package-manager'; import { readJsonFile } from '../fileutils'; @@ -23,7 +22,8 @@ function getPackageManagerInstallCommand(): string { } function tryGetCollection( - pluginPath: string, + workspaceRoot: string, + pluginName: string, jsonFile: string, propName: string ): T { @@ -32,7 +32,10 @@ function tryGetCollection( } try { - return readJsonFile(path.join(pluginPath, jsonFile))[propName]; + const jsonFilePath = require.resolve(`${pluginName}/${jsonFile}`, { + paths: [workspaceRoot], + }); + return readJsonFile(jsonFilePath)[propName]; } catch { return null; } @@ -43,16 +46,24 @@ export function getPluginCapabilities( pluginName: string ): PluginCapabilities { try { - const pluginPath = path.join(workspaceRoot, 'node_modules', pluginName); - const packageJson = readJsonFile(path.join(pluginPath, 'package.json')); + const packageJsonPath = require.resolve(`${pluginName}/package.json`, { + paths: [workspaceRoot], + }); + const packageJson = readJsonFile(packageJsonPath); return { name: pluginName, schematics: tryGetCollection( - pluginPath, + workspaceRoot, + pluginName, packageJson.schematics, 'schematics' ), - builders: tryGetCollection(pluginPath, packageJson.builders, 'builders'), + builders: tryGetCollection( + workspaceRoot, + pluginName, + packageJson.builders, + 'builders' + ), }; } catch { return null;