UNPKG

@nx/angular

Version:

The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: - Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, Playwright and Cypre

295 lines (293 loc) • 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateWorkspace = validateWorkspace; exports.createNxJson = createNxJson; exports.updateWorkspaceConfigDefaults = updateWorkspaceConfigDefaults; exports.updateRootTsConfig = updateRootTsConfig; exports.updatePackageJson = updatePackageJson; exports.updateRootEsLintConfig = updateRootEsLintConfig; exports.cleanupEsLintPackages = cleanupEsLintPackages; exports.createWorkspaceFiles = createWorkspaceFiles; exports.createRootKarmaConfig = createRootKarmaConfig; exports.getWorkspaceRootFileTypesInfo = getWorkspaceRootFileTypesInfo; exports.updateVsCodeRecommendedExtensions = updateVsCodeRecommendedExtensions; exports.deleteAngularJson = deleteAngularJson; exports.deleteGitKeepFilesIfNotNeeded = deleteGitKeepFilesIfNotNeeded; const devkit_1 = require("@nx/devkit"); const eslint_1 = require("@nx/eslint"); const setup_root_eslint_1 = require("@nx/eslint/src/generators/lint-project/setup-root-eslint"); const js_1 = require("@nx/js"); const default_base_1 = require("nx/src/utils/default-base"); const versions_1 = require("@nx/js/src/utils/versions"); const angular_json_1 = require("nx/src/adapter/angular-json"); const versions_2 = require("../../../utils/versions"); const path_1 = require("path"); function validateWorkspace(tree) { const errors = []; if (!tree.exists('package.json')) { errors.push('The "package.json" file could not be found.'); } if (!tree.exists('angular.json')) { errors.push('The "angular.json" file could not be found.'); } if (!errors.length) { return; } throw new Error(`The workspace cannot be migrated because of the following issues: - ${errors.join('\n ')}`); } function createNxJson(tree, options, defaultProject) { const targets = getWorkspaceCommonTargets(tree); (0, devkit_1.writeJson)(tree, 'nx.json', { defaultBase: options.defaultBase ?? (0, default_base_1.deduceDefaultBase)(), namedInputs: { sharedGlobals: [], default: ['{projectRoot}/**/*', 'sharedGlobals'], production: [ 'default', ...(targets.test ? [ '!{projectRoot}/tsconfig.spec.json', '!{projectRoot}/**/*.spec.[jt]s', '!{projectRoot}/karma.conf.js', ] : []), ...(targets.lint ? [ '!{projectRoot}/.eslintrc.json', '!{projectRoot}/eslint.config.cjs', ] : []), ].filter(Boolean), }, targetDefaults: { build: { dependsOn: ['^build'], inputs: ['production', '^production'], cache: true, }, test: targets.test ? { inputs: ['default', '^production', '{workspaceRoot}/karma.conf.js'], cache: true, } : undefined, lint: targets.lint ? { inputs: [ 'default', '{workspaceRoot}/.eslintrc.json', '{workspaceRoot}/eslint.config.cjs', ], cache: true, } : undefined, e2e: targets.e2e ? { inputs: ['default', '^production'], cache: true, } : undefined, }, defaultProject, }); } function getWorkspaceCommonTargets(tree) { const targets = { e2e: false, lint: false, test: false }; const projects = (0, devkit_1.getProjects)(tree); for (const [, project] of projects) { if (!targets.e2e && project.targets?.e2e) { targets.e2e = true; } if (!targets.lint && project.targets?.lint) { targets.lint = true; } if (!targets.test && project.targets?.test) { targets.test = true; } if (targets.e2e && targets.lint && targets.test) { return targets; } } return targets; } function updateWorkspaceConfigDefaults(tree) { const nxJson = (0, devkit_1.readNxJson)(tree); delete nxJson.newProjectRoot; if (nxJson.cli) { delete nxJson.defaultCollection; } (0, devkit_1.updateNxJson)(tree, nxJson); } function updateRootTsConfig(tree) { const tsconfig = (0, devkit_1.readJson)(tree, (0, js_1.getRootTsConfigPathInTree)(tree)); tsconfig.compilerOptions.paths ??= {}; tsconfig.compilerOptions.baseUrl = '.'; tsconfig.compilerOptions.rootDir = '.'; tsconfig.exclude = Array.from(new Set([...(tsconfig.exclude ?? []), 'node_modules', 'tmp'])); (0, devkit_1.writeJson)(tree, 'tsconfig.base.json', tsconfig); if (tree.exists('tsconfig.json')) { tree.delete('tsconfig.json'); } } function updatePackageJson(tree) { (0, devkit_1.updateJson)(tree, 'package.json', (packageJson) => { packageJson.scripts = packageJson.scripts ?? {}; Object.keys(packageJson.scripts).forEach((script) => { packageJson.scripts[script] = packageJson.scripts[script] .replace(/^ng /, 'nx ') .replace(/ ng /, ' nx '); }); packageJson.devDependencies = packageJson.devDependencies ?? {}; packageJson.dependencies = packageJson.dependencies ?? {}; if (!packageJson.devDependencies['@angular/cli']) { packageJson.devDependencies['@angular/cli'] = versions_2.angularDevkitVersion; } if (!packageJson.devDependencies['@nx/workspace'] && !packageJson.devDependencies['@nrwl/workspace']) { packageJson.devDependencies['@nx/workspace'] = versions_2.nxVersion; } if (!packageJson.devDependencies['nx']) { packageJson.devDependencies['nx'] = versions_2.nxVersion; } if (!packageJson.devDependencies['prettier']) { packageJson.devDependencies['prettier'] = versions_1.prettierVersion; } return packageJson; }); } async function updateRootEsLintConfig(tree, existingEsLintConfig, unitTestRunner) { await (0, eslint_1.lintInitGenerator)(tree, { addPlugin: false, }); if (!existingEsLintConfig) { // There was no eslint config in the root, so we set it up and use it as-is (0, setup_root_eslint_1.setupRootEsLint)(tree, { unitTestRunner }); return; } existingEsLintConfig.ignorePatterns = ['**/*']; if (!(existingEsLintConfig.plugins ?? []).includes('@nx')) { existingEsLintConfig.plugins = Array.from(new Set([...(existingEsLintConfig.plugins ?? []), '@nx'])); } existingEsLintConfig.overrides?.forEach((override) => { if (!override.parserOptions?.project) { return; } delete override.parserOptions.project; }); // add the @nx/enforce-module-boundaries rule existingEsLintConfig.overrides = [ ...(existingEsLintConfig.overrides ?? []), { files: ['*.ts', '*.tsx', '*.js', '*.jsx'], rules: { '@nx/enforce-module-boundaries': [ 'error', { enforceBuildableLibDependency: true, allow: [], depConstraints: [ { sourceTag: '*', onlyDependOnLibsWithTags: ['*'] }, ], }, ], }, }, ]; (0, devkit_1.writeJson)(tree, '.eslintrc.json', existingEsLintConfig); } function cleanupEsLintPackages(tree) { (0, devkit_1.updateJson)(tree, 'package.json', (json) => { if (json.devDependencies?.['@angular-eslint/builder']) { delete json.devDependencies['@angular-eslint/builder']; } if (json.dependencies?.['@angular-eslint/builder']) { delete json.dependencies['@angular-eslint/builder']; } if (json.devDependencies?.['@angular-eslint/schematics']) { delete json.devDependencies['@angular-eslint/schematics']; } if (json.dependencies?.['@angular-eslint/schematics']) { delete json.dependencies['@angular-eslint/schematics']; } return json; }); } async function createWorkspaceFiles(tree) { updateVsCodeRecommendedExtensions(tree); await (0, js_1.initGenerator)(tree, { skipFormat: true }); (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, '../files/root'), '.', { tmpl: '', dot: '.', rootTsConfigPath: (0, js_1.getRootTsConfigPathInTree)(tree), }); } function createRootKarmaConfig(tree) { (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, '../files/root-karma'), '.', { tmpl: '', }); } function getWorkspaceRootFileTypesInfo(tree, migrators) { const workspaceRootFileTypesInfo = { eslint: false, karma: false, }; if (tree.exists('.eslintrc.json')) { workspaceRootFileTypesInfo.eslint = true; } if (tree.exists('karma.conf.js')) { workspaceRootFileTypesInfo.karma = true; } if (workspaceRootFileTypesInfo.eslint && workspaceRootFileTypesInfo.karma) { return workspaceRootFileTypesInfo; } for (const migrator of migrators) { const projectInfo = migrator.getWorkspaceRootFileTypesInfo(); workspaceRootFileTypesInfo.eslint = workspaceRootFileTypesInfo.eslint || projectInfo.eslint; workspaceRootFileTypesInfo.karma = workspaceRootFileTypesInfo.karma || projectInfo.karma; if (workspaceRootFileTypesInfo.eslint && workspaceRootFileTypesInfo.karma) { return workspaceRootFileTypesInfo; } } return workspaceRootFileTypesInfo; } function updateVsCodeRecommendedExtensions(tree) { const recommendations = [ 'nrwl.angular-console', 'angular.ng-template', 'dbaeumer.vscode-eslint', 'esbenp.prettier-vscode', ]; if (tree.exists('.vscode/extensions.json')) { (0, devkit_1.updateJson)(tree, '.vscode/extensions.json', (json) => { json.recommendations = json.recommendations || []; recommendations.forEach((extension) => { if (!json.recommendations.includes(extension)) { json.recommendations.push(extension); } }); return json; }); } else { (0, devkit_1.writeJson)(tree, '.vscode/extensions.json', { recommendations, }); } } function deleteAngularJson(tree) { const projects = (0, angular_json_1.toNewFormat)((0, devkit_1.readJson)(tree, 'angular.json')).projects; if (!Object.keys(projects).length) { tree.delete('angular.json'); } } function deleteGitKeepFilesIfNotNeeded(tree) { if (tree.children('apps').length > 1 && tree.exists('apps/.gitkeep')) { tree.delete('apps/.gitkeep'); } if (tree.children('libs').length > 1 && tree.exists('libs/.gitkeep')) { tree.delete('libs/.gitkeep'); } }