UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

240 lines (239 loc) 9.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.installPlugins = installPlugins; exports.initHandler = initHandler; exports.detectPlugins = detectPlugins; const fs_1 = require("fs"); const semver_1 = require("semver"); const output_1 = require("../../utils/output"); const package_manager_1 = require("../../utils/package-manager"); const add_nx_scripts_1 = require("./implementation/dot-nx/add-nx-scripts"); const child_process_1 = require("../../utils/child-process"); const fileutils_1 = require("../../utils/fileutils"); const versions_1 = require("../../utils/versions"); const utils_1 = require("./implementation/utils"); const enquirer_1 = require("enquirer"); const child_process_2 = require("child_process"); const angular_1 = require("./implementation/angular"); const workspace_context_1 = require("../../utils/workspace-context"); const connect_to_nx_cloud_1 = require("../connect/connect-to-nx-cloud"); const add_nx_to_npm_repo_1 = require("./implementation/add-nx-to-npm-repo"); const add_nx_to_monorepo_1 = require("./implementation/add-nx-to-monorepo"); const nx_json_1 = require("../../config/nx-json"); const get_package_name_from_import_path_1 = require("../../utils/get-package-name-from-import-path"); function installPlugins(repoRoot, plugins, pmc, updatePackageScripts) { if (plugins.length === 0) { return; } (0, utils_1.addDepsToPackageJson)(repoRoot, plugins); (0, utils_1.runInstall)(repoRoot, pmc); output_1.output.log({ title: '🔨 Configuring plugins' }); for (const plugin of plugins) { (0, child_process_2.execSync)(`${pmc.exec} nx g ${plugin}:init --keepExistingVersions ${updatePackageScripts ? '--updatePackageScripts' : ''}`, { stdio: [0, 1, 2], cwd: repoRoot, windowsHide: true, }); } } async function initHandler(options) { process.env.NX_RUNNING_NX_INIT = 'true'; const version = process.env.NX_VERSION ?? ((0, semver_1.prerelease)(versions_1.nxVersion) ? 'next' : 'latest'); if (process.env.NX_VERSION) { output_1.output.log({ title: `Using version ${process.env.NX_VERSION}` }); } if (!(0, fs_1.existsSync)('package.json') || options.useDotNxInstallation) { if (process.platform !== 'win32') { console.log('Setting Nx up installation in `.nx`. You can run Nx commands like: `./nx --help`'); } else { console.log('Setting Nx up installation in `.nx`. You can run Nx commands like: `./nx.bat --help`'); } (0, add_nx_scripts_1.generateDotNxSetup)(version); const nxJson = (0, nx_json_1.readNxJson)(process.cwd()); const { plugins } = await detectPlugins(nxJson, options.interactive); plugins.forEach((plugin) => { (0, child_process_1.runNxSync)(`add ${plugin}`, { stdio: 'inherit', }); }); // invokes the wrapper, thus invoking the initial installation process (0, child_process_1.runNxSync)('--version', { stdio: 'ignore' }); return; } // TODO(jack): Remove this Angular logic once `@nx/angular` is compatible with inferred targets. if ((0, fs_1.existsSync)('angular.json')) { await (0, angular_1.addNxToAngularCliRepo)({ ...options, integrated: !!options.integrated, }); (0, utils_1.printFinalMessage)({ learnMoreLink: 'https://nx.dev/recipes/angular/migration/angular', }); return; } const packageJson = (0, fileutils_1.readJsonFile)('package.json'); if ((0, utils_1.isMonorepo)(packageJson)) { await (0, add_nx_to_monorepo_1.addNxToMonorepo)({ interactive: options.interactive, nxCloud: false, }); } else { await (0, add_nx_to_npm_repo_1.addNxToNpmRepo)({ interactive: options.interactive, nxCloud: false, }); } const learnMoreLink = (0, utils_1.isMonorepo)(packageJson) ? 'https://nx.dev/getting-started/tutorials/npm-workspaces-tutorial' : 'https://nx.dev/recipes/adopting-nx/adding-to-existing-project'; const useNxCloud = options.nxCloud ?? (options.interactive ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)() : false); const repoRoot = process.cwd(); const pmc = (0, package_manager_1.getPackageManagerCommand)(); (0, utils_1.createNxJsonFile)(repoRoot, [], [], {}); (0, utils_1.updateGitIgnore)(repoRoot); const nxJson = (0, nx_json_1.readNxJson)(repoRoot); output_1.output.log({ title: '🧐 Checking dependencies' }); const { plugins, updatePackageScripts } = await detectPlugins(nxJson, options.interactive); output_1.output.log({ title: '📦 Installing Nx' }); installPlugins(repoRoot, plugins, pmc, updatePackageScripts); if (useNxCloud) { output_1.output.log({ title: '🛠️ Setting up Nx Cloud' }); await (0, utils_1.initCloud)('nx-init'); } (0, utils_1.printFinalMessage)({ learnMoreLink, }); } const npmPackageToPluginMap = { // Generic JS tools eslint: '@nx/eslint', storybook: '@nx/storybook', // Bundlers vite: '@nx/vite', vitest: '@nx/vite', webpack: '@nx/webpack', rollup: '@nx/rollup', // Testing tools jest: '@nx/jest', cypress: '@nx/cypress', '@playwright/test': '@nx/playwright', // Frameworks detox: '@nx/detox', expo: '@nx/expo', next: '@nx/next', nuxt: '@nx/nuxt', 'react-native': '@nx/react-native', '@remix-run/dev': '@nx/remix', }; async function detectPlugins(nxJson, interactive, includeAngularCli) { let files = ['package.json'].concat((0, workspace_context_1.globWithWorkspaceContextSync)(process.cwd(), ['**/*/package.json'])); const currentPlugins = new Set((nxJson.plugins ?? []).map((p) => { const plugin = typeof p === 'string' ? p : p.plugin; return (0, get_package_name_from_import_path_1.getPackageNameFromImportPath)(plugin); })); const detectedPlugins = new Set(); for (const file of files) { if (!(0, fs_1.existsSync)(file)) continue; let packageJson; try { packageJson = (0, fileutils_1.readJsonFile)(file); } catch { // Could have malformed JSON for unit tests, etc. continue; } const deps = { ...packageJson.dependencies, ...packageJson.devDependencies, }; const _npmPackageToPluginMap = { ...npmPackageToPluginMap, }; if (includeAngularCli) { _npmPackageToPluginMap['@angular/cli'] = '@nx/angular'; } for (const [dep, plugin] of Object.entries(_npmPackageToPluginMap)) { if (deps[dep]) { detectedPlugins.add(plugin); } } } let gradlewFiles = ['gradlew', 'gradlew.bat'].concat((0, workspace_context_1.globWithWorkspaceContextSync)(process.cwd(), [ '**/gradlew', '**/gradlew.bat', ])); if (gradlewFiles.some((f) => (0, fs_1.existsSync)(f))) { detectedPlugins.add('@nx/gradle'); } // Remove existing plugins for (const plugin of detectedPlugins) { if (currentPlugins.has(plugin)) { detectedPlugins.delete(plugin); } } const plugins = Array.from(detectedPlugins); if (plugins.length === 0) { return { plugins: [], updatePackageScripts: false, }; } if (!interactive) { output_1.output.log({ title: `Recommended Plugins:`, bodyLines: [ `Adding these Nx plugins to integrate with the tools used in your workspace:`, ...plugins.map((p) => `- ${p}`), ], }); return { plugins, updatePackageScripts: true, }; } output_1.output.log({ title: `Recommended Plugins:`, bodyLines: [ `Add these Nx plugins to integrate with the tools used in your workspace.`, ], }); const pluginsToInstall = await (0, enquirer_1.prompt)([ { name: 'plugins', type: 'multiselect', message: `Which plugins would you like to add? Press <Space> to select and <Enter> to submit.`, choices: plugins.map((p) => ({ name: p, value: p })), /** * limit is missing from the interface but it limits the amount of options shown */ limit: process.stdout.rows - 4, // 4 leaves room for the header above, the prompt and some whitespace }, ]).then((r) => r.plugins); if (pluginsToInstall?.length === 0) return { plugins: [], updatePackageScripts: false, }; const updatePackageScripts = (0, fs_1.existsSync)('package.json') && (await (0, enquirer_1.prompt)([ { name: 'updatePackageScripts', type: 'autocomplete', message: `Do you want to start using Nx in your package.json scripts?`, choices: [ { name: 'Yes', }, { name: 'No', }, ], initial: 0, }, ]).then((r) => r.updatePackageScripts === 'Yes')); return { plugins: pluginsToInstall, updatePackageScripts }; }