Skip to content
95 changes: 95 additions & 0 deletions content/fundamentals/discovery-service.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions src/app/homepage/menu/menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {}
7 changes: 7 additions & 0 deletions src/app/homepage/pages/fundamentals/fundamentals.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -86,6 +87,11 @@ const routes: Routes = [
component: CircularDependencyComponent,
data: { title: 'Circular Dependency' },
},
{
path: 'discovery-service',
component: DiscoveryServiceComponent,
data: { title: 'Discovery Service' },
},
];

@NgModule({
Expand All @@ -102,6 +108,7 @@ const routes: Routes = [
LifecycleEventsComponent,
ModuleRefComponent,
LazyLoadingModulesComponent,
DiscoveryServiceComponent,
],
})
export class FundamentalsModule {}
Loading