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

111 lines (110 loc) 4.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = default_1; const tslib_1 = require("tslib"); const devkit_1 = require("@nx/devkit"); const ts = tslib_1.__importStar(require("typescript")); const file_change_recorder_1 = require("../../utils/file-change-recorder"); const versions_1 = require("../../utils/versions"); const projects_1 = require("../utils/projects"); async function default_1(tree) { const projects = await (0, projects_1.getProjectsFilteredByDependencies)([ 'npm:@angular/platform-server', ]); if (!projects.length) { return; } let isSsrInstalled = false; for (const graphNode of projects) { (0, devkit_1.visitNotIgnoredFiles)(tree, graphNode.data.root, (file) => { if (!file.endsWith('.ts') || file.endsWith('.d.ts')) { return; } const shouldInstallSsr = processFile(tree, file); if (shouldInstallSsr && !isSsrInstalled) { isSsrInstalled = true; (0, devkit_1.addDependenciesToPackageJson)(tree, { '@angular/ssr': versions_1.angularDevkitVersion }, {}, undefined, true); } }); } await (0, devkit_1.formatFiles)(tree); } function processFile(tree, filePath) { const content = tree.read(filePath, 'utf-8'); if (!content.includes('provideServerRendering') || !content.includes('@angular/platform-server')) { return false; } const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true); let platformServerHasProvideServerRendering = false; let platformServerImportNode; let ssrImportNode; const platformServerImports = new Set(); sourceFile.forEachChild((node) => { if (!ts.isImportDeclaration(node)) { return; } const moduleSpecifier = node.moduleSpecifier.getText(sourceFile); if (moduleSpecifier.includes('@angular/platform-server')) { platformServerImportNode = node; const importClause = node.importClause; if (importClause && importClause.namedBindings && ts.isNamedImports(importClause.namedBindings)) { const namedImports = importClause.namedBindings.elements.map((e) => e.getText(sourceFile)); namedImports.forEach((importName) => { if (importName === 'provideServerRendering') { platformServerHasProvideServerRendering = true; } else { platformServerImports.add(importName); } }); } } else if (moduleSpecifier.includes('@angular/ssr')) { ssrImportNode = node; } }); if (!platformServerHasProvideServerRendering) { return; } const recorder = new file_change_recorder_1.FileChangeRecorder(tree, filePath); const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, }); if (ssrImportNode?.importClause?.namedBindings && ts.isNamedImports(ssrImportNode.importClause.namedBindings)) { const namedBindingsNode = ssrImportNode.importClause .namedBindings; const updatedNamedBindingsNode = ts.factory.updateNamedImports(namedBindingsNode, [ ...namedBindingsNode.elements, ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('provideServerRendering')), ]); recorder.replace(namedBindingsNode, printer.printNode(ts.EmitHint.Unspecified, updatedNamedBindingsNode, sourceFile)); } else { /** * Add a new import statement with the needed named import in case it * doesn't exist yet or it doesn't have named imports. * * It would be quite uncommon to have an import from @angular/ssr without * named imports, but if that's the case, we'll just add an extra import * statement with the needed named import. */ recorder.insertLeft(0, `import { provideServerRendering } from '@angular/ssr';\n`); } if (platformServerImports.size > 0) { // we only collected platform server imports because there were named // imports, so we can safely use the type const namedBindingsNode = platformServerImportNode.importClause .namedBindings; const updatedNamedBindingsNode = ts.factory.updateNamedImports(namedBindingsNode, namedBindingsNode.elements.filter((e) => platformServerImports.has(e.getText(sourceFile)))); recorder.replace(namedBindingsNode, printer.printNode(ts.EmitHint.Unspecified, updatedNamedBindingsNode, sourceFile)); } else { recorder.remove(platformServerImportNode.getFullStart(), platformServerImportNode.getEnd()); } recorder.applyChanges(); return true; }