diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md new file mode 100644 index 0000000000..5a14c9ad8b --- /dev/null +++ b/content/fundamentals/discovery-service.md @@ -0,0 +1,95 @@ +### Discovery Service + +The `DiscoveryService` is a utility provided by `@nestjs/core` that allows developers to dynamically discover providers, controllers, and other metadata within a NestJS application. This can be particularly useful for building plugins, decorators, or features that rely on runtime introspection. + +Before using the `DiscoveryService`, you need to import the `DiscoveryModule` in your module: + +```typescript +@@filename(example.module) +import { Module } from '@nestjs/common'; +import { DiscoveryModule } from '@nestjs/core'; +import { ExampleService } from './example.service'; + +@Module({ + imports: [DiscoveryModule], + providers: [ExampleService], +}) +export class ExampleModule {} +``` + +Then, inject `DiscoveryService` into a provider or service: + +```typescript +@@filename(example.service) +@Injectable() +export class ExampleService { + constructor(private readonly discoveryService: DiscoveryService) {} +} +@@switch +@Injectable() +@Dependencies(DiscoveryService) +export class ExampleService { + constructor(discoveryService) { + this.discoveryService = discoveryService; + } +} +``` + +> info **Hint** The `DiscoveryService` class is imported from the `@nestjs/core` package. + +#### Discovering Providers + +You can retrieve all registered providers in the application: + +```typescript +const providers = this.discoveryService.getProviders(); +console.log(providers); +``` + +Each provider object contains information about the instance, token, and metadata. + +#### Discovering Controllers + +Retrieve all registered controllers: + +```typescript +const controllers = this.discoveryService.getControllers(); +console.log(controllers); +``` + +#### Finding Metadata + +`DiscoveryService` can help find metadata attached to providers or controllers. This is useful when working with decorators that add metadata. Let's see an example. Suppose you have a custom decorator that adds metadata to a provider: + +```typescript +import { DiscoveryService } from '@nestjs/core'; + +export const Pets = DiscoveryService.createDecorator(); +``` + +And you use it in a service: + +```typescript +import { Injectable } from '@nestjs/common'; +import { Pets } from './custom-metadata.decorator'; + +@Injectable() +@Pets('cats') +export class CustomService {} +``` + +Now, you can use `DiscoveryService` to find all providers with this metadata: + +```typescript +const providers = this.discoveryService.getProviders(); + +const [provider] = providers.filter( + (prov) => this.discoveryService.getMetadataByDecorator(Pets, prov) === 'cats', +); + +console.log('Providers with cats metadata:', provider); +``` + +### Conclusion + +`DiscoveryService` is a powerful tool for runtime introspection in NestJS applications. It allows you to discover providers, controllers, and metadata dynamically, making it useful for plugin development, custom decorators, and advanced framework-level features. diff --git a/src/app/homepage/menu/menu.component.ts b/src/app/homepage/menu/menu.component.ts index 6ad9995d1b..f3930bc17c 100644 --- a/src/app/homepage/menu/menu.component.ts +++ b/src/app/homepage/menu/menu.component.ts @@ -59,6 +59,10 @@ export class MenuComponent implements OnInit { title: 'Circular dependency', path: '/fundamentals/circular-dependency', }, + { + title: 'Discovery Service', + path: '/fundamentals/discovery-service', + }, { title: 'Module reference', path: '/fundamentals/module-ref', diff --git a/src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts b/src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts new file mode 100644 index 0000000000..904d7f1ad7 --- /dev/null +++ b/src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts @@ -0,0 +1,9 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { BasePageComponent } from '../../page/page.component'; + +@Component({ + selector: 'app-discovery-service', + templateUrl: './discovery-service.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DiscoveryServiceComponent extends BasePageComponent {} diff --git a/src/app/homepage/pages/fundamentals/fundamentals.module.ts b/src/app/homepage/pages/fundamentals/fundamentals.module.ts index a926aeb51f..81170cf28d 100644 --- a/src/app/homepage/pages/fundamentals/fundamentals.module.ts +++ b/src/app/homepage/pages/fundamentals/fundamentals.module.ts @@ -4,6 +4,7 @@ import { RouterModule, Routes } from '@angular/router'; import { SharedModule } from '../../../shared/shared.module'; import { AsyncComponentsComponent } from './async-components/async-components.component'; import { CircularDependencyComponent } from './circular-dependency/circular-dependency.component'; +import { DiscoveryServiceComponent } from './discovery-service/discovery-service.component'; import { DependencyInjectionComponent } from './dependency-injection/dependency-injection.component'; import { DynamicModulesComponent } from './dynamic-modules/dynamic-modules.component'; import { LifecycleEventsComponent } from './lifecycle-events/lifecycle-events.component'; @@ -86,6 +87,11 @@ const routes: Routes = [ component: CircularDependencyComponent, data: { title: 'Circular Dependency' }, }, + { + path: 'discovery-service', + component: DiscoveryServiceComponent, + data: { title: 'Discovery Service' }, + }, ]; @NgModule({ @@ -102,6 +108,7 @@ const routes: Routes = [ LifecycleEventsComponent, ModuleRefComponent, LazyLoadingModulesComponent, + DiscoveryServiceComponent, ], }) export class FundamentalsModule {}