From 6f0c8be8c4f5947d7ef8b0cbb6216100bd4a4491 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 16:50:31 +0100 Subject: [PATCH 01/10] docs: add discovery service documentation --- content/fundamentals/discovery-service.md | 119 ++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 content/fundamentals/discovery-service.md diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md new file mode 100644 index 0000000000..1fda085c36 --- /dev/null +++ b/content/fundamentals/discovery-service.md @@ -0,0 +1,119 @@ +### 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. + +## Installation + +`DiscoveryService` is part of `@nestjs/core`, so it does not require separate installation. You can use it directly within your NestJS application. + +## Importing DiscoveryService and DiscoveryModule + +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. + +## Use Cases + +### 1. 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. + +### 2. Discovering Controllers + +Retrieve all registered controllers: + +```typescript +const controllers = this.discoveryService.getControllers(); +console.log(controllers); +``` + +### 3. Finding Metadata + +`DiscoveryService` can help find metadata attached to providers or controllers. This is useful when working with decorators that add metadata. + +```typescript +const providers = this.discoveryService.getProviders(); + +for (const provider of providers) { + const metadata = this.reflector.get('custom:metadataKey', provider.instance.constructor); + if (metadata) { + console.log(`Metadata found:`, metadata); + } +} +``` + +## Example: Custom Decorator with DiscoveryService + +Suppose you have a custom decorator that adds metadata to a provider: + +```typescript +import { SetMetadata } from '@nestjs/common'; + +export const CustomMetadata = (value: string) => SetMetadata('custom:metadataKey', value); +``` + +And you use it in a service: + +```typescript +import { Injectable } from '@nestjs/common'; +import { CustomMetadata } from './custom-metadata.decorator'; + +@Injectable() +@CustomMetadata('example-value') +export class CustomService {} +``` + +Now, you can use `DiscoveryService` to find all providers with this metadata: + +```typescript +const providers = this.discoveryService.getProviders(); + +const filteredProviders = providers.filter((provider) => { + if (!provider.instance) return null; + return !!this.reflector.get(metadataPathToken, provider.instance.constructor); +}); + +console.log('Providers with custom metadata:', filteredProviders); +``` + +## 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. From 7ccee7cefa94199aab73e7814cf33a547f225697 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:00:40 +0100 Subject: [PATCH 02/10] feat: add discovery service components --- .../discovery-service/discovery-service.component.ts | 9 +++++++++ .../homepage/pages/fundamentals/fundamentals.module.ts | 6 ++++++ 2 files changed, 15 insertions(+) create mode 100644 src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts 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..8ae24317cd --- /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: './dependency-injection.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..d51ffa7e18 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({ From 10b34391959ac948fc83edd67af97838e496751c Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:01:39 +0100 Subject: [PATCH 03/10] feat: add DiscoveryServiceComponent to the declarations of module --- src/app/homepage/pages/fundamentals/fundamentals.module.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/homepage/pages/fundamentals/fundamentals.module.ts b/src/app/homepage/pages/fundamentals/fundamentals.module.ts index d51ffa7e18..81170cf28d 100644 --- a/src/app/homepage/pages/fundamentals/fundamentals.module.ts +++ b/src/app/homepage/pages/fundamentals/fundamentals.module.ts @@ -108,6 +108,7 @@ const routes: Routes = [ LifecycleEventsComponent, ModuleRefComponent, LazyLoadingModulesComponent, + DiscoveryServiceComponent, ], }) export class FundamentalsModule {} From e0419013701317e3ae1bb9e5825b901603469091 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:04:28 +0100 Subject: [PATCH 04/10] feat: update templateUrl of discovery service component --- .../discovery-service/discovery-service.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 8ae24317cd..904d7f1ad7 100644 --- a/src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts +++ b/src/app/homepage/pages/fundamentals/discovery-service/discovery-service.component.ts @@ -3,7 +3,7 @@ import { BasePageComponent } from '../../page/page.component'; @Component({ selector: 'app-discovery-service', - templateUrl: './dependency-injection.component.html', + templateUrl: './discovery-service.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) export class DiscoveryServiceComponent extends BasePageComponent {} From ce7507be5056975ec6bc51c2db83ee6a574c5e2f Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:14:09 +0100 Subject: [PATCH 05/10] feat: add discovery service to menu list --- src/app/homepage/menu/menu.component.ts | 4 ++++ 1 file changed, 4 insertions(+) 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', From 32868dcf25a273e32a3681aaf9eff2e5b4b4b31d Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:20:46 +0100 Subject: [PATCH 06/10] docs: better titles for discovery service --- content/fundamentals/discovery-service.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md index 1fda085c36..a6945d0f21 100644 --- a/content/fundamentals/discovery-service.md +++ b/content/fundamentals/discovery-service.md @@ -2,11 +2,11 @@ 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. -## Installation +### Installation `DiscoveryService` is part of `@nestjs/core`, so it does not require separate installation. You can use it directly within your NestJS application. -## Importing DiscoveryService and DiscoveryModule +### Importing DiscoveryService and DiscoveryModule Before using the `DiscoveryService`, you need to import the `DiscoveryModule` in your module: @@ -43,9 +43,9 @@ export class ExampleService { > info **Hint** The `DiscoveryService` class is imported from the `@nestjs/core` package. -## Use Cases +### Use Cases -### 1. Discovering Providers +#### 1. Discovering Providers You can retrieve all registered providers in the application: @@ -56,7 +56,7 @@ console.log(providers); Each provider object contains information about the instance, token, and metadata. -### 2. Discovering Controllers +#### 2. Discovering Controllers Retrieve all registered controllers: @@ -65,7 +65,7 @@ const controllers = this.discoveryService.getControllers(); console.log(controllers); ``` -### 3. Finding Metadata +#### 3. Finding Metadata `DiscoveryService` can help find metadata attached to providers or controllers. This is useful when working with decorators that add metadata. @@ -80,7 +80,7 @@ for (const provider of providers) { } ``` -## Example: Custom Decorator with DiscoveryService +##### Example: Custom Decorator with DiscoveryService Suppose you have a custom decorator that adds metadata to a provider: @@ -114,6 +114,6 @@ const filteredProviders = providers.filter((provider) => { console.log('Providers with custom metadata:', filteredProviders); ``` -## Conclusion +### 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. From 8635c61f3208f3854189a79c1294d9a7e40d8187 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:28:52 +0100 Subject: [PATCH 07/10] docs: remove installation and numbering from discovery service --- content/fundamentals/discovery-service.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md index a6945d0f21..8bd6e2525b 100644 --- a/content/fundamentals/discovery-service.md +++ b/content/fundamentals/discovery-service.md @@ -2,11 +2,8 @@ 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. -### Installation -`DiscoveryService` is part of `@nestjs/core`, so it does not require separate installation. You can use it directly within your NestJS application. - -### Importing DiscoveryService and DiscoveryModule +### Import Module & Service Before using the `DiscoveryService`, you need to import the `DiscoveryModule` in your module: @@ -45,7 +42,7 @@ export class ExampleService { ### Use Cases -#### 1. Discovering Providers +#### Discovering Providers You can retrieve all registered providers in the application: @@ -56,7 +53,7 @@ console.log(providers); Each provider object contains information about the instance, token, and metadata. -#### 2. Discovering Controllers +#### Discovering Controllers Retrieve all registered controllers: @@ -65,7 +62,7 @@ const controllers = this.discoveryService.getControllers(); console.log(controllers); ``` -#### 3. Finding Metadata +#### Finding Metadata `DiscoveryService` can help find metadata attached to providers or controllers. This is useful when working with decorators that add metadata. From 386b837199a6d84835f515cfe8ff51bcf74f233a Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 10 Mar 2025 17:46:22 +0100 Subject: [PATCH 08/10] docs: remove unnecessary titles --- content/fundamentals/discovery-service.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md index 8bd6e2525b..6618adfd56 100644 --- a/content/fundamentals/discovery-service.md +++ b/content/fundamentals/discovery-service.md @@ -2,9 +2,6 @@ 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. - -### Import Module & Service - Before using the `DiscoveryService`, you need to import the `DiscoveryModule` in your module: ```typescript @@ -40,8 +37,6 @@ export class ExampleService { > info **Hint** The `DiscoveryService` class is imported from the `@nestjs/core` package. -### Use Cases - #### Discovering Providers You can retrieve all registered providers in the application: From 8b082f1d151a1835dc913775e7d5e29142f38897 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 24 Mar 2025 18:03:19 +0100 Subject: [PATCH 09/10] feat: use getMetadataByDecorator of discover service instead of SetMetadata --- content/fundamentals/discovery-service.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md index 6618adfd56..9b53680411 100644 --- a/content/fundamentals/discovery-service.md +++ b/content/fundamentals/discovery-service.md @@ -77,19 +77,19 @@ for (const provider of providers) { Suppose you have a custom decorator that adds metadata to a provider: ```typescript -import { SetMetadata } from '@nestjs/common'; +import { DiscoveryService } from '@nestjs/core'; -export const CustomMetadata = (value: string) => SetMetadata('custom:metadataKey', value); +export const Pets = DiscoveryService.createDecorator(); ``` And you use it in a service: ```typescript import { Injectable } from '@nestjs/common'; -import { CustomMetadata } from './custom-metadata.decorator'; +import { Pets } from './custom-metadata.decorator'; @Injectable() -@CustomMetadata('example-value') +@Pets('cats') export class CustomService {} ``` @@ -98,12 +98,11 @@ Now, you can use `DiscoveryService` to find all providers with this metadata: ```typescript const providers = this.discoveryService.getProviders(); -const filteredProviders = providers.filter((provider) => { - if (!provider.instance) return null; - return !!this.reflector.get(metadataPathToken, provider.instance.constructor); -}); +const [provider] = providers.filter( + (prov) => this.discoveryService.getMetadataByDecorator(Pets, prov) === 'cats', +); -console.log('Providers with custom metadata:', filteredProviders); +console.log('Providers with cats metadata:', provider); ``` ### Conclusion From 16f3212824855cf896b82756885ecb5b607cc2e8 Mon Sep 17 00:00:00 2001 From: Vahid Najafi <vahid.vdn@gmail.com> Date: Mon, 24 Mar 2025 18:10:25 +0100 Subject: [PATCH 10/10] feat: remove unnecessary code --- content/fundamentals/discovery-service.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/content/fundamentals/discovery-service.md b/content/fundamentals/discovery-service.md index 9b53680411..5a14c9ad8b 100644 --- a/content/fundamentals/discovery-service.md +++ b/content/fundamentals/discovery-service.md @@ -59,22 +59,7 @@ 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. - -```typescript -const providers = this.discoveryService.getProviders(); - -for (const provider of providers) { - const metadata = this.reflector.get('custom:metadataKey', provider.instance.constructor); - if (metadata) { - console.log(`Metadata found:`, metadata); - } -} -``` - -##### Example: Custom Decorator with DiscoveryService - -Suppose you have a custom decorator that adds metadata to a provider: +`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';