nx/packages/angular/src/migrations/update-16-1-0/remove-render-module-platform-server-exports.ts
2023-05-02 16:19:56 +01:00

88 lines
2.7 KiB
TypeScript

import type { Tree } from '@nx/devkit';
import { formatFiles, visitNotIgnoredFiles } from '@nx/devkit';
import * as ts from 'typescript';
import { FileChangeRecorder } from '../../utils/file-change-recorder';
export default async function (tree: Tree) {
visitNotIgnoredFiles(tree, '/', (path) => {
if (path.endsWith('.ts') && !path.endsWith('.d.ts')) {
const content = tree.read(path, 'utf8');
if (
content.includes('@angular/platform-server') &&
content.includes('renderModule')
) {
const source = ts.createSourceFile(
path,
content.toString().replace(/^\uFEFF/, ''),
ts.ScriptTarget.Latest,
true
);
let recorder: FileChangeRecorder | undefined;
let printer: ts.Printer | undefined;
ts.forEachChild(source, function analyze(node) {
if (
!(
ts.isExportDeclaration(node) &&
node.moduleSpecifier &&
ts.isStringLiteral(node.moduleSpecifier) &&
node.moduleSpecifier.text === '@angular/platform-server' &&
node.exportClause &&
ts.isNamedExports(node.exportClause)
)
) {
// Not a @angular/platform-server named export.
return;
}
const exportClause = node.exportClause;
const newElements: ts.ExportSpecifier[] = [];
for (const element of exportClause.elements) {
if (element.name.text !== 'renderModule') {
newElements.push(element);
}
}
if (newElements.length === exportClause.elements.length) {
// No changes
return;
}
recorder ??= new FileChangeRecorder(tree, path);
if (newElements.length) {
// Update named exports as there are leftovers.
const newExportClause = ts.factory.updateNamedExports(
exportClause,
newElements
);
printer ??= ts.createPrinter();
const fix = printer.printNode(
ts.EmitHint.Unspecified,
newExportClause,
source
);
const index = exportClause.getStart();
const length = exportClause.getWidth();
recorder.remove(index, index + length);
recorder.insertLeft(index, fix);
} else {
// Delete export as no exports remain.
recorder.remove(node.getStart(), node.getStart() + node.getWidth());
}
ts.forEachChild(node, analyze);
});
if (recorder) {
recorder.applyChanges();
}
}
}
});
await formatFiles(tree);
}