diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts index 70a8c21244..af516d2286 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -13,7 +13,8 @@ import { updateWorkspace, WorkspaceDefinition, getAppConfigPath, - removeEmptyElementsFromArrayLiteral, + cleanEmptyExprFromModule, + cleanEmptyExprFromProviders, } from '../../utils'; import { ThemeOptionsEnum } from './theme-options.enum'; import { findNodes, getDecoratorMetadata, getMetadataField } from '../../utils/angular/ast-utils'; @@ -81,7 +82,7 @@ function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsE insertImports(selectedProject, targetThemeName), insertProviders(selectedProject, targetThemeName), formatFile(appModulePath), - cleanNgModuleCommasRule(appModulePath, isStandalone), + cleanEmptyExpressions(appModulePath, isStandalone), ]); }; } @@ -364,7 +365,7 @@ export const formatFile = (filePath: string): Rule => { }; }; -export function cleanNgModuleCommasRule(modulePath: string, isStandalone: boolean): Rule { +export function cleanEmptyExpressions(modulePath: string, isStandalone: boolean): Rule { return (host: Tree) => { const buffer = host.read(modulePath); if (!buffer) throw new SchematicsException(`Cannot read ${modulePath}`); @@ -376,57 +377,11 @@ export function cleanNgModuleCommasRule(modulePath: string, isStandalone: boolea true, ); const recorder = host.beginUpdate(modulePath); - const printer = ts.createPrinter(); if (isStandalone) { - const varStatements = findNodes(source, ts.isVariableStatement); - - for (const stmt of varStatements) { - const declList = stmt.declarationList; - for (const decl of declList.declarations) { - if (!decl.initializer || !ts.isObjectLiteralExpression(decl.initializer)) continue; - - const obj = decl.initializer; - - const providersProp = obj.properties.find( - prop => - ts.isPropertyAssignment(prop) && - ts.isIdentifier(prop.name) && - prop.name.text === 'providers', - ) as ts.PropertyAssignment; - - if (!providersProp || !ts.isArrayLiteralExpression(providersProp.initializer)) continue; - - const arrayLiteral = providersProp.initializer; - const cleanedArray = removeEmptyElementsFromArrayLiteral(arrayLiteral); - - recorder.remove(arrayLiteral.getStart(), arrayLiteral.getWidth()); - recorder.insertLeft( - arrayLiteral.getStart(), - printer.printNode(ts.EmitHint.Expression, cleanedArray, source), - ); - } - } + cleanEmptyExprFromProviders(source, recorder); } else { - const ngModuleNode = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0]; - if (!ngModuleNode) return host; - - const metadataKeys = ['imports', 'providers']; - for (const key of metadataKeys) { - const metadataField = getMetadataField(ngModuleNode as ts.ObjectLiteralExpression, key); - if (!metadataField.length) continue; - - const assignment = metadataField[0] as ts.PropertyAssignment; - const arrayLiteral = assignment.initializer as ts.ArrayLiteralExpression; - - const cleanedArray = removeEmptyElementsFromArrayLiteral(arrayLiteral); - - recorder.remove(arrayLiteral.getStart(), arrayLiteral.getWidth()); - recorder.insertLeft( - arrayLiteral.getStart(), - printer.printNode(ts.EmitHint.Expression, cleanedArray, source), - ); - } + cleanEmptyExprFromModule(source, recorder); } host.commitUpdate(recorder); return host; diff --git a/npm/ng-packs/packages/schematics/src/utils/ng-module.ts b/npm/ng-packs/packages/schematics/src/utils/ng-module.ts index 30dafd427b..f048588d5f 100644 --- a/npm/ng-packs/packages/schematics/src/utils/ng-module.ts +++ b/npm/ng-packs/packages/schematics/src/utils/ng-module.ts @@ -1,10 +1,11 @@ -import { SchematicsException, Tree } from '@angular-devkit/schematics'; +import { SchematicsException, Tree, UpdateRecorder } from '@angular-devkit/schematics'; import { getMainFilePath } from './angular/standalone/util'; import * as ts from 'typescript'; import { getAppModulePath, getDecoratorMetadata, getMetadataField } from './angular'; import { createSourceFile } from '../commands/change-theme/index'; import { normalize, Path } from '@angular-devkit/core'; import * as path from 'path'; +import { removeEmptyElementsFromArrayLiteral } from './ast'; export const hasImportInNgModule = async ( host: Tree, @@ -98,3 +99,26 @@ export async function findAppRoutesModulePath( return null; } + +export function cleanEmptyExprFromModule(source: ts.SourceFile, recorder: UpdateRecorder): void { + const ngModuleNode = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0]; + if (!ngModuleNode) return; + + const printer = ts.createPrinter(); + const metadataKeys = ['imports', 'providers']; + for (const key of metadataKeys) { + const metadataField = getMetadataField(ngModuleNode as ts.ObjectLiteralExpression, key); + if (!metadataField.length) continue; + + const assignment = metadataField[0] as ts.PropertyAssignment; + const arrayLiteral = assignment.initializer as ts.ArrayLiteralExpression; + + const cleanedArray = removeEmptyElementsFromArrayLiteral(arrayLiteral); + + recorder.remove(arrayLiteral.getStart(), arrayLiteral.getWidth()); + recorder.insertLeft( + arrayLiteral.getStart(), + printer.printNode(ts.EmitHint.Expression, cleanedArray, source), + ); + } +} diff --git a/npm/ng-packs/packages/schematics/src/utils/standalone.ts b/npm/ng-packs/packages/schematics/src/utils/standalone.ts index ad9197c2aa..982c56875e 100644 --- a/npm/ng-packs/packages/schematics/src/utils/standalone.ts +++ b/npm/ng-packs/packages/schematics/src/utils/standalone.ts @@ -1,9 +1,11 @@ -import { SchematicsException, Tree } from '@angular-devkit/schematics'; +import { SchematicsException, Tree, UpdateRecorder } from '@angular-devkit/schematics'; import { findBootstrapApplicationCall, getMainFilePath } from './angular/standalone/util'; import { findAppConfig } from './angular/standalone/app_config'; import * as ts from 'typescript'; import { normalize, Path } from '@angular-devkit/core'; import * as path from 'path'; +import { findNodes } from './angular'; +import { removeEmptyElementsFromArrayLiteral } from './ast'; export const getAppConfigPath = (host: Tree, mainFilePath: string): string => { const bootstrapCall = findBootstrapApplicationCall(host, mainFilePath); @@ -92,3 +94,35 @@ export const hasProviderInStandaloneAppConfig = async ( const providersArray = callExpressions[0].initializer as ts.ArrayLiteralExpression; return providersArray.elements.some(el => el.getText().includes(providerName)); }; + +export function cleanEmptyExprFromProviders(source: ts.SourceFile, recorder: UpdateRecorder): void { + const varStatements = findNodes(source, ts.isVariableStatement); + const printer = ts.createPrinter(); + + for (const stmt of varStatements) { + const declList = stmt.declarationList; + for (const decl of declList.declarations) { + if (!decl.initializer || !ts.isObjectLiteralExpression(decl.initializer)) continue; + + const obj = decl.initializer; + + const providersProp = obj.properties.find( + prop => + ts.isPropertyAssignment(prop) && + ts.isIdentifier(prop.name) && + prop.name.text === 'providers', + ) as ts.PropertyAssignment; + + if (!providersProp || !ts.isArrayLiteralExpression(providersProp.initializer)) continue; + + const arrayLiteral = providersProp.initializer; + const cleanedArray = removeEmptyElementsFromArrayLiteral(arrayLiteral); + + recorder.remove(arrayLiteral.getStart(), arrayLiteral.getWidth()); + recorder.insertLeft( + arrayLiteral.getStart(), + printer.printNode(ts.EmitHint.Expression, cleanedArray, source), + ); + } + } +}