ModuleManager
The first stage of processing metadata passed to module decorators (such as @rootModule or @featureModule) occurs within the ModuleManager service.
It recursively scans all modules starting from the root module, passes decorator options through ModuleNormalizer, and stores the collected normalized metadata as NormalizedModuleMeta instances.
Scanning and Normalization Workflow
The initialization process begins when the application invokes moduleManager.scanAppModule(rootModule):
- Root Module Normalization: Decorator options of the root module are passed to
ModuleNormalizer, which validates them and forms initial normalized metadata. - Recursive Dependency Traversal:
ModuleManagertraverses all modules specified inimportsandexportsarrays, building the complete application module map. - Mixin Decorator Execution: If a module uses extended mixin decorators (such as
@restModuleor custom@mixin*), corresponding module mixins are executed to normalize extended metadata. - Validation and Integrity Checking: Module imports and exports are verified for correctness and configuration conflicts.
Dynamic Module Manipulation
After scanning completes, ModuleManager provides an API for inspecting and programmatically modifying module metadata before AppInitializer builds providers and extensions:
getMetadata(modRefId): Retrieves normalized metadata for a specified module.setImports(modRefId, ...imports): Adds module imports to a module's normalized metadata without directly editing its class decorator.removeImport(modRefId, importToFind): Removes specific imports from a module's normalized metadata.
This mechanism enables flexible application customization during testing (e.g., swapping modules or providers) or dynamically attaching feature modules at application startup.