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

223 lines (219 loc) • 9.64 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.addVitestAngular = addVitestAngular; exports.addVitestAnalog = addVitestAnalog; const devkit_1 = require("@nx/devkit"); const devkit_internals_1 = require("nx/src/devkit-internals"); const semver_1 = require("semver"); const versions_1 = require("../../utils/versions"); const version_utils_1 = require("./version-utils"); async function addVitestAngular(tree, options) { validateVitestVersion(tree); const executor = options.useNxUnitTestRunnerExecutor ? '@nx/angular:unit-test' : '@angular/build:unit-test'; const project = (0, devkit_1.readProjectConfiguration)(tree, options.name); project.targets ??= {}; project.targets.test = { executor, options: {} }; (0, devkit_1.updateProjectConfiguration)(tree, options.name, project); const nxJson = (0, devkit_1.readNxJson)(tree); nxJson.targetDefaults ??= {}; nxJson.targetDefaults[executor] ??= { cache: true, inputs: nxJson.namedInputs && 'production' in nxJson.namedInputs ? ['default', '^production'] : ['default', '^default'], }; (0, devkit_1.updateNxJson)(tree, nxJson); configureTypeScriptForVitest(tree, options.projectRoot); addVitestScreenshotsToGitIgnore(tree); if (!options.skipPackageJson) { const pkgVersions = (0, version_utils_1.versions)(tree, { minAngularMajorVersion: 21 }); const angularDevkitVersion = (0, version_utils_1.getInstalledAngularDevkitVersion)(tree) ?? pkgVersions.angularDevkitVersion; (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@angular/build': angularDevkitVersion, jsdom: pkgVersions.jsdomVersion, vitest: pkgVersions.vitestVersion, }, undefined, true); } } async function addVitestAnalog(tree, options) { const { major: angularMajorVersion } = (0, version_utils_1.getInstalledAngularVersionInfo)(tree); if (!options.skipPackageJson) { const angularDevkitVersion = (0, version_utils_1.getInstalledAngularDevkitVersion)(tree) ?? (0, version_utils_1.versions)(tree).angularDevkitVersion; const devDependencies = { '@angular/build': angularDevkitVersion, }; // Add compatible vitest/jsdom versions BEFORE calling configurationGenerator // so that @nx/vitest respects existing versions if (angularMajorVersion < 21) { const pkgVersions = (0, version_utils_1.versions)(tree); devDependencies['vitest'] = pkgVersions.vitestVersion; devDependencies['jsdom'] = pkgVersions.jsdomVersion; } (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, true); } (0, devkit_1.ensurePackage)('@nx/vitest', versions_1.nxVersion); const { configurationGenerator } = await Promise.resolve().then(() => __importStar(require('@nx/vitest/generators'))); await configurationGenerator(tree, { project: options.name, uiFramework: 'angular', testEnvironment: 'jsdom', coverageProvider: 'v8', addPlugin: options.addPlugin ?? false, skipFormat: options.skipFormat, skipPackageJson: options.skipPackageJson, }); createAnalogSetupFile(tree, options, angularMajorVersion); } function validateVitestVersion(tree) { let installedVitestVersion = null; // Try to get the actual installed version from node_modules try { const { packageJson } = (0, devkit_internals_1.readModulePackageJson)('vitest'); installedVitestVersion = packageJson.version; } catch { } const pkgVersions = (0, version_utils_1.versions)(tree, { minAngularMajorVersion: 21 }); const requiredRange = pkgVersions.vitestVersion; if (installedVitestVersion) { if (!(0, semver_1.satisfies)(installedVitestVersion, requiredRange, { includePrerelease: true, })) { throw new Error(`The installed vitest version "${installedVitestVersion}" is not compatible with the version range Angular requires: "${requiredRange}".`); } return; } // not installed, get it from package.json installedVitestVersion = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'vitest'); if (!installedVitestVersion) { // not declared anywhere, it'll be installed with the correct version return; } if ((0, semver_1.valid)(installedVitestVersion)) { if (!(0, semver_1.satisfies)(installedVitestVersion, requiredRange, { includePrerelease: true, })) { throw new Error(`The installed vitest version "${installedVitestVersion}" is not compatible with the version range Angular requires: "${requiredRange}".`); } } else if ((0, semver_1.validRange)(installedVitestVersion)) { // it's a range from package.json, check if it intersects with the required range if (!(0, semver_1.intersects)(installedVitestVersion, requiredRange, { includePrerelease: true, })) { throw new Error(`The declared vitest version range "${installedVitestVersion}" does not overlap with the version range Angular requires: "${requiredRange}". When installed, this may cause compatibility issues.`); } } else { // it can be anything, we don't have a way to validate it // log a warning and continue devkit_1.logger.warn(`The declared vitest version "${installedVitestVersion}" is not a valid semver range, ` + `so we can't validate if it's compatible with the version range Angular requires: "${requiredRange}". ` + `The generation will continue, but you may encounter issues if the version is not compatible.`); } } function configureTypeScriptForVitest(tree, projectRoot) { (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.spec.json'), { extends: './tsconfig.json', compilerOptions: { outDir: `${(0, devkit_1.offsetFromRoot)(projectRoot)}dist/out-tsc`, types: ['vitest/globals'], }, include: ['src/**/*.ts', 'src/**/*.d.ts'], }); const projectTsconfigPath = (0, devkit_1.joinPathFragments)(projectRoot, 'tsconfig.json'); (0, devkit_1.updateJson)(tree, projectTsconfigPath, (json) => { json.references ??= []; if (!json.references.some((ref) => ref.path === './tsconfig.spec.json')) { json.references.push({ path: './tsconfig.spec.json' }); } return json; }); } function addVitestScreenshotsToGitIgnore(tree) { if (tree.exists('.gitignore')) { let content = tree.read('.gitignore', 'utf-8'); if (/^__screenshots__\/$/gm.test(content)) { return; } content = `${content}\n__screenshots__/\n`; tree.write('.gitignore', content); } else { devkit_1.logger.warn(`Couldn't find .gitignore file to update`); } } function createAnalogSetupFile(tree, options, angularMajorVersion) { let setupFile; if (angularMajorVersion >= 21) { setupFile = `import '@angular/compiler'; import '@analogjs/vitest-angular/setup-snapshots'; import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed'; setupTestBed(${options.zoneless ? '' : '{ zoneless: false }'}); `; } else if (angularMajorVersion === 20) { setupFile = `import '@angular/compiler'; import '@analogjs/vitest-angular/setup-zone'; import { BrowserTestingModule, platformBrowserTesting, } from '@angular/platform-browser/testing'; import { getTestBed } from '@angular/core/testing'; getTestBed().initTestEnvironment( BrowserTestingModule, platformBrowserTesting(), ); `; } else { setupFile = `import '@analogjs/vitest-angular/setup-zone'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; import { getTestBed } from '@angular/core/testing'; getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), ); `; } tree.write((0, devkit_1.joinPathFragments)(options.projectRoot, 'src/test-setup.ts'), setupFile); }