From d4cc6dc9f45441ecbab0f8e7fb185e1bb25b9f44 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Mon, 21 Apr 2025 15:54:55 +0300 Subject: [PATCH] docs update --- .../schematics/src/utils/ng-module.ts | 47 ++++++++++++++--- .../schematics/src/utils/standalone.ts | 52 +++++++++++++++++++ 2 files changed, 93 insertions(+), 6 deletions(-) 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 f048588d5f..ca2d327eb6 100644 --- a/npm/ng-packs/packages/schematics/src/utils/ng-module.ts +++ b/npm/ng-packs/packages/schematics/src/utils/ng-module.ts @@ -7,6 +7,21 @@ import { normalize, Path } from '@angular-devkit/core'; import * as path from 'path'; import { removeEmptyElementsFromArrayLiteral } from './ast'; +/** + * Checks whether a specific import or provider exists in the specified metadata + * array (`imports`, `providers`, etc.) of the `NgModule` decorator in the AppModule. + * + * This function locates the AppModule file of the given Angular project, + * parses its AST, and inspects the specified metadata array to determine + * if it includes an element matching the provided string (e.g., `CommonModule`, `HttpClientModule`). + * + * @param host - The virtual file system tree used by Angular schematics. + * @param projectName - The name of the Angular project. + * @param metadataFn - The name (string) to match against the elements of the metadata array. + * @param metadataName - The metadata field to search in (e.g., 'imports', 'providers'). Defaults to 'imports'. + * @returns A promise that resolves to `true` if the metadata function is found, or `false` otherwise. + * @throws SchematicsException if the AppModule file or expected metadata is not found or malformed. + */ export const hasImportInNgModule = async ( host: Tree, projectName: string, @@ -23,14 +38,9 @@ export const hasImportInNgModule = async ( const source = createSourceFile(host, appModulePath); - console.log('AppModule content:\n', buffer.toString('utf-8')); - // Get the NgModule decorator metadata const ngModuleDecorator = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0]; - console.log( - 'Found NgModule decorators:', - getDecoratorMetadata(source, 'NgModule', '@angular/core'), - ); + if (!ngModuleDecorator) { throw new SchematicsException('The app module does not found'); } @@ -50,6 +60,20 @@ export const hasImportInNgModule = async ( return elements.some(f => f.getText().match(metadataFn)); }; +/** + * Attempts to locate the path of the `AppRoutingModule` file that is imported + * within the root AppModule file of an Angular application. + * + * This function reads the AppModule file (resolved from the main file path), + * parses its AST, and searches for an import declaration that imports + * `AppRoutingModule`. Once found, it resolves the import path to a normalized + * file path relative to the workspace root. + * + * @param tree - The virtual file system tree used by Angular schematics. + * @param mainFilePath - The path to the main entry file of the Angular application (typically `main.ts`). + * @returns A normalized workspace-relative path to the AppRoutingModule file if found, or `null` otherwise. + * @throws If the route file path is resolved but the file does not exist in the tree. + */ export async function findAppRoutesModulePath( tree: Tree, mainFilePath: string, @@ -100,6 +124,17 @@ export async function findAppRoutesModulePath( return null; } +/** + * Cleans up empty or invalid expressions (e.g., extra commas) from the `imports` and `providers` + * arrays in the NgModule decorator of an Angular module file. + * + * This function parses the source file's AST, locates the `NgModule` decorator, and processes + * the `imports` and `providers` metadata fields. If these fields contain array literals with + * empty slots (such as trailing or double commas), they are removed and the array is rewritten. + * + * @param source - The TypeScript source file containing the Angular module. + * @param recorder - The recorder used to apply changes to the source file. + */ export function cleanEmptyExprFromModule(source: ts.SourceFile, recorder: UpdateRecorder): void { const ngModuleNode = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0]; if (!ngModuleNode) return; diff --git a/npm/ng-packs/packages/schematics/src/utils/standalone.ts b/npm/ng-packs/packages/schematics/src/utils/standalone.ts index 982c56875e..60364eb976 100644 --- a/npm/ng-packs/packages/schematics/src/utils/standalone.ts +++ b/npm/ng-packs/packages/schematics/src/utils/standalone.ts @@ -7,12 +7,36 @@ import * as path from 'path'; import { findNodes } from './angular'; import { removeEmptyElementsFromArrayLiteral } from './ast'; +/** + * Retrieves the file path of the application's configuration used in a standalone + * Angular application setup. + * + * This function locates the `bootstrapApplication` call in the main entry file and + * resolves the path to the configuration object passed to it (typically `appConfig`). + * + * @param host - The virtual file system tree used by Angular schematics. + * @param mainFilePath - The path to the main entry file of the Angular application (e.g., `main.ts`). + * @returns The resolved file path of the application's configuration, or an empty string if not found. + */ export const getAppConfigPath = (host: Tree, mainFilePath: string): string => { const bootstrapCall = findBootstrapApplicationCall(host, mainFilePath); const appConfig = findAppConfig(bootstrapCall, host, mainFilePath); return appConfig?.filePath || ''; }; +/** + * Attempts to locate the file path of the `routes` array used in a standalone + * Angular application configuration. + * + * This function resolves the application's config file (typically where `routes` is defined or imported), + * parses the file, and inspects its import declarations to find the import associated with `routes`. + * It then resolves and normalizes the file path of the `routes` definition and returns it. + * + * @param tree - The virtual file system tree used by Angular schematics. + * @param mainFilePath - The path to the main entry file of the Angular application (e.g., `main.ts`). + * @returns The normalized workspace-relative path to the file where `routes` is defined, or `null` if not found. + * @throws If the `routes` import path is found but the file does not exist in the tree. + */ export function findAppRoutesPath(tree: Tree, mainFilePath: string): Path | null { const appConfigPath = getAppConfigPath(tree, mainFilePath); if (!appConfigPath || !tree.exists(appConfigPath)) return null; @@ -60,6 +84,20 @@ export function findAppRoutesPath(tree: Tree, mainFilePath: string): Path | null return null; } +/** + * Checks whether a specific provider is registered in the `providers` array of the + * standalone application configuration (typically within `app.config.ts`) in an Angular project. + * + * This function reads and parses the application configuration file, looks for the + * `providers` property in the configuration object, and checks whether it includes + * the specified provider name. + * + * @param host - The virtual file system tree used by Angular schematics. + * @param projectName - The name of the Angular project. + * @param providerName - The name of the provider to search for (as a string match). + * @returns A promise that resolves to `true` if the provider is found, otherwise `false`. + * @throws SchematicsException if the app config file cannot be read. + */ export const hasProviderInStandaloneAppConfig = async ( host: Tree, projectName: string, @@ -95,6 +133,20 @@ export const hasProviderInStandaloneAppConfig = async ( return providersArray.elements.some(el => el.getText().includes(providerName)); }; +/** + * Cleans up empty or invalid expressions (e.g., extra or trailing commas) from the + * `providers` array within a standalone Angular application configuration object. + * + * This function parses the source file's AST to locate variable declarations that + * define an object literal. It then searches for a `providers` property and removes + * any empty elements from its array literal, replacing it with a cleaned version. + * + * Typically used in Angular schematics to ensure the `providers` array in `app.config.ts` + * is free of empty slots after modifications. + * + * @param source - The TypeScript source file containing the app configuration. + * @param recorder - The recorder used to apply changes to the source file. + */ export function cleanEmptyExprFromProviders(source: ts.SourceFile, recorder: UpdateRecorder): void { const varStatements = findNodes(source, ts.isVariableStatement); const printer = ts.createPrinter();