UNPKG

nx

Version:

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

231 lines (230 loc) โ€ข 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addNxToCraRepo = addNxToCraRepo; const child_process_1 = require("child_process"); const node_fs_1 = require("node:fs"); const path_1 = require("path"); const fileutils_1 = require("../../../../utils/fileutils"); const output_1 = require("../../../../utils/output"); const package_manager_1 = require("../../../../utils/package-manager"); const check_for_custom_webpack_setup_1 = require("./check-for-custom-webpack-setup"); const check_for_uncommitted_changes_1 = require("./check-for-uncommitted-changes"); const clean_up_files_1 = require("./clean-up-files"); const read_name_from_package_json_1 = require("./read-name-from-package-json"); const rename_js_to_jsx_1 = require("./rename-js-to-jsx"); const tsconfig_setup_1 = require("./tsconfig-setup"); const write_craco_config_1 = require("./write-craco-config"); const write_vite_config_1 = require("./write-vite-config"); const write_vite_index_html_1 = require("./write-vite-index-html"); const connect_to_nx_cloud_1 = require("../../../connect/connect-to-nx-cloud"); async function addNxToCraRepo(options) { if (!options.force) { (0, check_for_uncommitted_changes_1.checkForUncommittedChanges)(); (0, check_for_custom_webpack_setup_1.checkForCustomWebpackSetup)(); } output_1.output.log({ title: '๐Ÿณ Nx initialization' }); const normalizedOptions = await normalizeOptions(options); await reorgnizeWorkspaceStructure(normalizedOptions); } function installDependencies(options) { const dependencies = [ '@testing-library/jest-dom', 'eslint-config-react-app', 'web-vitals', 'jest-watch-typeahead', ]; if (options.isVite) { dependencies.push('vite', 'vitest', '@vitejs/plugin-react'); } else { dependencies.push('@craco/craco', 'cross-env', 'react-scripts', 'tsconfig-paths-webpack-plugin'); } (0, child_process_1.execSync)(`${options.pmc.addDev} ${dependencies.join(' ')}`, { stdio: [0, 1, 2], windowsHide: true, }); } async function normalizeOptions(options) { const packageManager = (0, package_manager_1.detectPackageManager)(); const pmc = (0, package_manager_1.getPackageManagerCommand)(packageManager); const appIsJs = !(0, fileutils_1.fileExists)(`tsconfig.json`); const reactAppName = (0, read_name_from_package_json_1.readNameFromPackageJson)(); const packageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(process.cwd(), 'package.json')); const deps = { ...packageJson.dependencies, ...packageJson.devDependencies, }; const isCRA5 = /^[^~]?5/.test(deps['react-scripts']); const npmVersion = (0, child_process_1.execSync)('npm -v', { windowsHide: true, }).toString(); // Should remove this check 04/2023 once Node 14 & npm 6 reach EOL const npxYesFlagNeeded = !npmVersion.startsWith('6'); // npm 7 added -y flag to npx const isVite = options.vite; const isStandalone = !options.integrated; const nxCloud = options.nxCloud ?? (options.interactive ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)() : false); return { ...options, nxCloud, packageManager, pmc, appIsJs, reactAppName, isCRA5, npxYesFlagNeeded, isVite, isStandalone, }; } /** * - Create a temp workspace * - Move all files to temp workspace * - Add bundler to temp workspace * - Move files back to root * - Clean up unused files */ async function reorgnizeWorkspaceStructure(options) { createTempWorkspace(options); moveFilesToTempWorkspace(options); await addBundler(options); output_1.output.log({ title: '๐Ÿงถ Updating .gitignore file' }); (0, child_process_1.execSync)(`echo "node_modules" >> .gitignore`, { stdio: [0, 1, 2], windowsHide: true, }); (0, child_process_1.execSync)(`echo "dist" >> .gitignore`, { stdio: [0, 1, 2], windowsHide: true, }); process.chdir('..'); copyFromTempWorkspaceToRoot(); cleanUpUnusedFilesAndAddConfigFiles(options); output_1.output.log({ title: '๐Ÿ™‚ Please be patient, one final step remaining!' }); output_1.output.log({ title: '๐Ÿ“ฆ Installing dependencies' }); installDependencies(options); if (options.isVite) { const indexPath = options.isStandalone ? 'index.html' : (0, path_1.join)('apps', options.reactAppName, 'index.html'); const oldIndexPath = options.isStandalone ? (0, path_1.join)('public', 'index.html') : (0, path_1.join)('apps', options.reactAppName, 'public', 'index.html'); output_1.output.note({ title: `A new ${indexPath} has been created. Compare it to the previous ${oldIndexPath} file and make any changes needed, then delete the previous file.`, }); } } function createTempWorkspace(options) { (0, node_fs_1.rmSync)('temp-workspace', { recursive: true, force: true }); (0, child_process_1.execSync)(`npx ${options.npxYesFlagNeeded ? '-y' : ''} create-nx-workspace@latest temp-workspace --appName=${options.reactAppName} --preset=react-monorepo --style=css --bundler=${options.isVite ? 'vite' : 'webpack'} --packageManager=${options.packageManager} ${options.nxCloud ? '--nxCloud=yes' : '--nxCloud=skip'} ${options.addE2e ? '--e2eTestRunner=playwright' : '--e2eTestRunner=none'}`, { stdio: [0, 1, 2], windowsHide: true }); output_1.output.log({ title: '๐Ÿ‘‹ Welcome to Nx!' }); output_1.output.log({ title: '๐Ÿงน Clearing unused files' }); (0, node_fs_1.cpSync)((0, path_1.join)('temp-workspace', 'apps', options.reactAppName, 'project.json'), 'project.json', { recursive: true }); (0, node_fs_1.rmSync)((0, path_1.join)('temp-workspace', 'apps', options.reactAppName), { recursive: true, force: true, }); (0, node_fs_1.rmSync)('node_modules', { recursive: true, force: true }); } function copyPackageJsonDepsFromTempWorkspace() { const repoRoot = process.cwd(); let rootPackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(repoRoot, 'package.json')); const tempWorkspacePackageJson = (0, fileutils_1.readJsonFile)((0, path_1.join)(repoRoot, 'temp-workspace', 'package.json')); rootPackageJson = overridePackageDeps('dependencies', rootPackageJson, tempWorkspacePackageJson); rootPackageJson = overridePackageDeps('devDependencies', rootPackageJson, tempWorkspacePackageJson); rootPackageJson.scripts = {}; // remove existing scripts (0, fileutils_1.writeJsonFile)((0, path_1.join)(repoRoot, 'package.json'), rootPackageJson); (0, fileutils_1.writeJsonFile)((0, path_1.join)(repoRoot, 'temp-workspace', 'package.json'), rootPackageJson); } function overridePackageDeps(depConfigName, base, override) { if (!base[depConfigName]) { base[depConfigName] = override[depConfigName]; return base; } const deps = override[depConfigName]; Object.keys(deps).forEach((dep) => { if (base.dependencies?.[dep]) { delete base.dependencies[dep]; } if (base.devDependencies?.[dep]) { delete base.devDependencies[dep]; } base[depConfigName][dep] = deps[dep]; }); return base; } function moveSync(src, dest) { const destParentDir = (0, path_1.dirname)(dest); (0, node_fs_1.mkdirSync)(destParentDir, { recursive: true }); (0, node_fs_1.rmSync)(dest, { recursive: true, force: true }); return (0, node_fs_1.renameSync)(src, dest); } function moveFilesToTempWorkspace(options) { output_1.output.log({ title: '๐Ÿšš Moving your React app in your new Nx workspace' }); copyPackageJsonDepsFromTempWorkspace(); const requiredCraFiles = [ 'project.json', 'package.json', 'src', 'public', options.appIsJs ? null : 'tsconfig.json', options.packageManager === 'yarn' ? 'yarn.lock' : null, options.packageManager === 'pnpm' ? 'pnpm-lock.yaml' : null, options.packageManager === 'npm' ? 'package-lock.json' : null, options.packageManager === 'bun' ? 'bun.lockb' : null, ]; const optionalCraFiles = ['README.md']; const filesToMove = [...requiredCraFiles, ...optionalCraFiles].filter(Boolean); filesToMove.forEach((f) => { try { moveSync(f, options.isStandalone ? (0, path_1.join)('temp-workspace', f) : (0, path_1.join)('temp-workspace', 'apps', options.reactAppName, f)); } catch (error) { if (requiredCraFiles.includes(f)) { throw error; } } }); process.chdir('temp-workspace'); } async function addBundler(options) { if (options.isVite) { output_1.output.log({ title: '๐Ÿง‘โ€๐Ÿ”ง Setting up Vite' }); const { addViteCommandsToPackageScripts } = await Promise.resolve().then(() => require('./add-vite-commands-to-package-scripts')); addViteCommandsToPackageScripts(options.reactAppName, options.isStandalone); (0, write_vite_config_1.writeViteConfig)(options.reactAppName, options.isStandalone, options.appIsJs); (0, write_vite_index_html_1.writeViteIndexHtml)(options.reactAppName, options.isStandalone, options.appIsJs); await (0, rename_js_to_jsx_1.renameJsToJsx)(options.reactAppName, options.isStandalone); } else { output_1.output.log({ title: '๐Ÿง‘โ€๐Ÿ”ง Setting up craco + Webpack' }); const { addCracoCommandsToPackageScripts } = await Promise.resolve().then(() => require('./add-craco-commands-to-package-scripts')); addCracoCommandsToPackageScripts(options.reactAppName, options.isStandalone); (0, write_craco_config_1.writeCracoConfig)(options.reactAppName, options.isCRA5, options.isStandalone); output_1.output.log({ title: '๐Ÿ›ฌ Skip CRA preflight check since Nx manages the monorepo', }); (0, child_process_1.execSync)(`echo "SKIP_PREFLIGHT_CHECK=true" > .env`, { stdio: [0, 1, 2], windowsHide: true, }); } } function copyFromTempWorkspaceToRoot() { output_1.output.log({ title: '๐Ÿšš Folder restructuring.' }); (0, node_fs_1.readdirSync)('temp-workspace').forEach((f) => { moveSync((0, path_1.join)('temp-workspace', f), f); }); } function cleanUpUnusedFilesAndAddConfigFiles(options) { output_1.output.log({ title: '๐Ÿงน Cleaning up.' }); (0, clean_up_files_1.cleanUpFiles)(options.reactAppName, options.isStandalone); output_1.output.log({ title: "๐Ÿ“ƒ Extend the app's tsconfig.json from the base" }); (0, tsconfig_setup_1.setupTsConfig)(options.reactAppName, options.isStandalone); if (options.isStandalone) { (0, node_fs_1.rmSync)('apps', { recursive: true, force: true }); } }