### Install Class Validator Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md If you don't already have `class-validator` installed, you should install it to complement the plugin's functionality. ```bash npm install class-validator ``` ```bash yarn add class-validator ``` ```bash pnpm add class-validator ``` -------------------------------- ### Install NestJS ESLint Plugin Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md Install the plugin as a development dependency using your preferred package manager. ```bash pnpm add -D @darraghor/eslint-plugin-nestjs-typed ``` ```bash npm i -D @darraghor/eslint-plugin-nestjs-typed ``` ```bash bun install -d @darraghor/eslint-plugin-nestjs-typed ``` -------------------------------- ### Install ESLint Plugin NestJS Typed Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md Install the plugin using npm, yarn, or pnpm. This is the first step to integrating the plugin into your project. ```bash npm install --save-dev @darraghor/eslint-plugin-nestjs-typed ``` ```bash yarn add -D @darraghor/eslint-plugin-nestjs-typed ``` ```bash pnpm add -D @darraghor/eslint-plugin-nestjs-typed ``` -------------------------------- ### Passing Example: Primitive Array Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example passes because 'exampleProperty' is an array of a primitive type (string). Primitive arrays do not require a @Type() decorator. ```typescript class ExampleDto { @ApiProperty({ isArray: true, }) @Allow() exampleProperty!: string[]; } ``` -------------------------------- ### Passing Example: String Array with isArray Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-returning-array-should-set-array.md This example passes because the property is an array and `isArray: true` is correctly specified with the `type` option. ```typescript class TestClass { @ApiPropertyOptional({type: String, isArray: true}) thisIsAProp!: Array; } ``` -------------------------------- ### Passing example: All properties decorated correctly Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-have-explicit-defined.md Demonstrates a class where all properties have appropriate validation decorators. ```typescript export class CreateOrganisationDto { @IsDefined() otherProperty!: MyClass; @IsOptional() someStringProperty?: string; @ValidateIf(o => !o.someStringProperty) @Length(10, 20) someOtherProperty?: string } ``` -------------------------------- ### Passing Example: Enum Array with isArray Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-returning-array-should-set-array.md This example passes because the property is an array and `isArray: true` is correctly specified. ```typescript class TestClass { @ApiPropertyOptional({enumName: "MyEnum" isArray:true}) thisIsAProp!: MyEnum[]; } ``` -------------------------------- ### Failing Examples: ApiOperation Missing Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-method-should-specify-api-operation.md Methods decorated only with HTTP method decorators (e.g., @Get, @All) without a corresponding @ApiOperation decorator will fail this rule. Ensure @ApiOperation is present for all such methods. ```typescript class TestClassD { @Get() public getAll(): Promise { return []; } } class TestClassE { @All() public getAll(): Promise { return []; } } ``` -------------------------------- ### Param Matches Route Parameter in @Get Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/param-decorator-name-matches-route-param.md This example passes because the 'uuid' parameter in the @Param() decorator matches the ':uuid' defined in the @Get() decorator. ```typescript import { Controller, Get, Param, Request } from "@nestjs/common"; import { ApiOkResponse } from "@nestjs/swagger"; @Controller("custom-bot") export class CustomBotController { constructor() {} @Get(":uuid") @ApiOkResponse({type: CustomBot}) findOne( @Param("uuid") uuid: string, @Request() request: RequestWithUser ): Promise { return this.customBotService.findOne(uuid, request.user.uuid); } } ``` -------------------------------- ### Passing Example: Required Property with @ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This is a valid example where a required property is correctly decorated with `@ApiProperty()`. ```typescript class TestClass { @Expose() @ApiProperty() thisIsAStringProp!: string; } ``` -------------------------------- ### Passing Example: Optional Property with @ApiPropertyOptional Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This is a valid example where an optional property is correctly decorated with `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiPropertyOptional() thisIsAStringProp?: string; } ``` -------------------------------- ### Passing Example: Required Property with @ApiProperty and Description Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This is a valid example where a required property is correctly decorated with `@ApiProperty()` and includes an additional `description` property. ```typescript class TestClass { @Expose() @ApiProperty({ description: 'A test property' }) thisIsAStringProp!: string; } ``` -------------------------------- ### Rule Configuration Example Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/injectable-should-be-provided.md Shows the default configuration for the 'injectable-should-be-provided' rule, including source directory and path filtering options. This configuration should be overridden to match your project structure. ```json "@darraghor/nestjs-typed/injectable-should-be-provided": [ "error", { "src": ["src/**/*.ts"], "filterFromPaths": ["node_modules", ".test.", ".spec."], }, ], ``` -------------------------------- ### Passing Examples: ApiOperation Specified Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-method-should-specify-api-operation.md Methods decorated with @Get and @ApiOperation are considered valid. This applies to methods with and without other response decorators like @ApiOkResponse. ```typescript class TestClassA { @Get() @ApiOperation({description: "test description"}) @ApiOkResponse({type: String, isArray: true}) public getAll(): Promise { return []; } } class TestClassB { @Get() @ApiOperation({description: "test description"}) public getAll(): Promise { return []; } } ``` -------------------------------- ### Configure No Duplicate Decorators Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/no-duplicate-decorators.md Example of how to configure the rule with a custom list of decorators to check. This overwrites default configurations. ```json "@darraghor/nestjs-typed/no-duplicate-decorators": [ "error", {customList: ["SomeValidatedDecoratorName", "DiscoverDecorator"]}, ] ``` -------------------------------- ### Provider with Matching Injection and Factory Parameters Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/provided-injected-should-match-factory-parameters.md This example demonstrates a correctly configured provider where the injected service `MyService` matches the factory parameter `config`. This configuration passes the rule. ```typescript export const MyOtherInjectableProvider: NotAProvider = { provide: MyOtherInjectable, useFactory: async (config: MyService): Promise => { return new MyOtherInjectable(); }, inject: [MyService], }; ``` -------------------------------- ### Passing: Summary Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Example demonstrating a correctly capitalized 'summary' property in an @ApiOperation decorator. ```typescript class TestClass { @Post("logout") @ApiOperation({ summary: "Clears the access-token cookie" }) postLogout(@Res() res: Response) { return; } } ``` -------------------------------- ### Valid Controller with Multiple Path Segments (kebab-case) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Example of a controller with multiple path segments, all adhering to the correct kebab-case format. ```typescript @Controller('users') class TestClass { @Get('active-users/by-date') public getActiveUsers() { return []; } } ``` -------------------------------- ### Failing Example: Missing isArray for Array Type Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-returning-array-should-set-array.md This example fails because the property is declared as an array (`Array`) but `isArray: true` is missing in the decorator. ```typescript class TestClass { @ApiPropertyOptional({type: String}) thisIsAProp!: Array; } ``` -------------------------------- ### Failing Example: Unnecessary isArray for Non-Array Type Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-returning-array-should-set-array.md This example fails because `isArray: true` is specified, but the property is not an array type (`string`). ```typescript class TestClass { @ApiPropertyOptional({type: String, isArray: true}) thisIsAProp!: string; } ``` -------------------------------- ### Passing example: No class-validator decorators used Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-have-explicit-defined.md This example passes because the rule ignores classes that do not have any class-validator decorators. ```typescript export class CreateOrganisationDto { otherProperty!: MyClass; someStringProperty?: string; } ``` -------------------------------- ### Typo in Param Decorator Fails Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/param-decorator-name-matches-route-param.md This example fails because there is a typo ('uui') in the @Param() decorator, which does not match the ':uuid' in the @Get() decorator. ```typescript import { Controller, Get, Param, Request } from "@nestjs/common"; import { ApiOkResponse } from "@nestjs/swagger"; @Controller("custom-bot") export class CustomBotController { constructor() {} @Get(":uuid") @ApiOkResponse({type: CustomBot}) findOne( @Param("uui") uuid: string, @Request() request: RequestWithUser ): Promise { return this.customBotService.findOne(uuid, request.user.uuid); } } ``` -------------------------------- ### Controller with ApiTags (Passes) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/controllers-should-supply-api-tags.md This example demonstrates a controller that correctly includes the @ApiTags decorator, satisfying the rule. ```typescript @ApiTags("my-group-of-methods") @Controller("my-controller") class TestClass {} ``` -------------------------------- ### Failing: Both Summary and Description Not Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Highlights a case where both 'summary' and 'description' properties in @ApiOperation fail to start with an uppercase letter. ```typescript class TestClass { @Get() @ApiOperation({ summary: "get all items", // Should start with 'G' description: "this method returns all available items" // Should start with 'T' }) public getAll(): Promise { return []; } } ``` -------------------------------- ### Passing Example: No Class-Validator Decorator Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example passes because the 'members' property does not have any class-validator decorators, even though it's a non-primitive type. ```typescript export class CreateOrganizationDto { @ApiProperty({type: Person, isArray: true}) members!: Person | Date; } ``` -------------------------------- ### Passing: Description Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Example showing a correctly capitalized 'description' property within an @ApiOperation decorator. ```typescript class TestClass { @Get() @ApiOperation({ description: "Returns all items" }) public getAll(): Promise { return []; } } ``` -------------------------------- ### Configuration: Disable Controller Param Check Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/param-decorator-name-matches-route-param.md This configuration disables the check for route parameters within the @Controller() decorator. The example fails because 'uui' in @Param() does not match ':uuid' in @Get(), and the controller check is off. ```typescript "@darraghor/param-decorator-name-matches-route-param": [ "error", { shouldCheckController: false }, ], ``` ```typescript import { Controller, Get, Param, Request } from "@nestjs/common"; import { ApiOkResponse } from "@nestjs/swagger"; import { SOME_PATH } from '../shared-paths'; @Controller(SOME_PATH) export class CustomBotController { constructor() {} @Get(":uuid") @ApiOkResponse({type: CustomBot}) findOne( @Param("uui") uuid: string, @Request() request: RequestWithUser ): Promise { return this.customBotService.findOne(uuid, request.user.uuid); } } ``` -------------------------------- ### Passing Example: Optional Property (Union with Undefined) with @ApiPropertyOptional Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This is a valid example where an optional property (union with undefined) is correctly decorated with `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiPropertyOptional() thisIsAStringProp: string | undefined; } ``` -------------------------------- ### Incorrectly Includes ':' in Param Decorator Fails Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/param-decorator-name-matches-route-param.md This example fails because the ':' character is incorrectly included in the @Param() decorator ('@Param(":uuid")'). The ':' should only be used in the route definition (e.g., @Get(':uuid')), not in the @Param() decorator itself. ```typescript import { Controller, Get, Param, Request } from "@nestjs/common"; import { ApiOkResponse } from "@nestjs/swagger"; @Controller("custom-bot") export class CustomBotController { constructor() {} @Get(":uuid") @ApiOkResponse({type: CustomBot}) findOne( @Param(":uuid") uuid: string, @Request() request: RequestWithUser ): Promise { return this.customBotService.findOne(uuid, request.user.uuid); } } ``` -------------------------------- ### Failing Example: Optional Modifier with Default Value Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because using the optional modifier (`?`) together with `@ApiProperty()` is inconsistent, even with an initializer. It should be `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiProperty() thisIsAStringProp?: string = "default"; } ``` -------------------------------- ### Failing Example: Redundant `required: true` in @ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because `required: true` is redundant in the `@ApiProperty` decorator, as properties are required by default in Swagger/OpenAPI. ```typescript class TestClass { @Expose() @ApiProperty({ required: true }) thisIsAStringProp!: string; } ``` -------------------------------- ### Failing Example: Optional Property with @ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because the property `thisIsAStringProp` is optional (marked with `?`) but uses the `@ApiProperty()` decorator instead of `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiProperty() thisIsAStringProp?: string; } ``` -------------------------------- ### Passing Example: Non-primitive with @Type Decorator Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example passes because the 'members' property, which is a non-primitive 'Person' class, has both @ApiProperty and @Type decorators. ```typescript export class CreateOrganizationDto { @ApiProperty({type: Person, isArray: true}) @IsDefined() @Type(() => Person) members!: Person; } ``` -------------------------------- ### ValidationPipe with default configuration Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validation-pipe-should-use-forbid-unknown.md This example passes because the default configuration of ValidationPipe is assumed to be acceptable by the rule. However, it's recommended to explicitly set `forbidUnknownValues: true` for clarity and security. ```typescript const validationPipeB = new ValidationPipe(); ``` -------------------------------- ### Controller Protected by AuthGuard Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-methods-should-be-guarded.md This example shows a passing scenario where an entire controller is protected by an AuthGuard. Applying the guard at the controller level ensures all its endpoints inherit the protection. ```typescript @UseGuards(AuthGuard("jwt")) class TestClass { @Get() public getAll(): Promise { return []; } @Get() public getOne(): Promise { return "1"; } } ``` -------------------------------- ### Failing Example: Optional Property with Default Value Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because a class field with a default value (initializer) is treated as optional from the DTO/API perspective and should use `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiProperty() thisIsAStringProp: string = "default"; } ``` -------------------------------- ### Invalid Decorator Usage (Fails) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/no-duplicate-decorators.md Shows an example where a decorator is applied twice to the same property, which will be flagged by the rule. ```typescript @DiscoverDecorator() class MyClass { @DiscoverDecorator() @DiscoverDecorator() myProperty: string; } ``` -------------------------------- ### Passing Example: Primitive Type Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example passes because the 'members' property is a primitive type (boolean). Primitive types do not require a @Type decorator. ```typescript export class CreateOrganizationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) @IsBoolean() members!: boolean; } ``` -------------------------------- ### Passing Example: Optional Property with Default Value and @ApiPropertyOptional Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This is a valid example where a class field with a default value is treated as optional and correctly decorated with `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiPropertyOptional() thisIsAStringProp: string = "default"; } ``` -------------------------------- ### Failing example: Missing @IsOptional() or @ValidateIf() Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-have-explicit-defined.md This class fails the rule because `someStringProperty` is missing either `@IsOptional()` or `@ValidateIf()` while also having `@IsString()`. ```typescript export class CreateOrganisationDto { @IsDefined() otherProperty!: MyClass; @IsString() someStringProperty?: string; } ``` -------------------------------- ### Failing Example: Optional Property (Union with Undefined) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because the property `thisIsAStringProp` is defined as a union with `undefined`, making it optional, but uses `@ApiProperty()` instead of `@ApiPropertyOptional()`. ```typescript class TestClass { @Expose() @ApiProperty() thisIsAStringProp: string | undefined; } ``` -------------------------------- ### Endpoint Protected by AuthGuard Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-methods-should-be-guarded.md This example demonstrates a passing case where a single endpoint is protected by an AuthGuard. Ensure the guard is correctly applied using the @UseGuards decorator. ```typescript class TestClass { @Get() @UseGuards(AuthGuard('jwt')) public getAll(): Promise { return []; } } ``` -------------------------------- ### Failing Example: Redundant `required: true` with Other Properties Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example also fails due to a redundant `required: true` in the `@ApiProperty` decorator, even when other properties like `description` are present. ```typescript class TestClass { @Expose() @ApiProperty({ required: true, description: 'A test property' }) thisIsAStringProp!: string; } ``` -------------------------------- ### Configuring Additional Custom API Response Decorators Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-method-should-specify-api-response.md This example shows how to configure the rule to recognize custom decorators like 'ApiPaginatedResponse' as valid API response definitions. ```typescript { "@darraghor/nestjs-typed/api-method-should-specify-api-response": [ "error", {additionalCustomApiResponseDecorators: ["ApiPaginatedResponse"]}, ], } ``` -------------------------------- ### Failing Example: Required Property with @ApiPropertyOptional Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md This example fails because the property `thisIsAStringProp` is a required property (definite assertion `!`) but uses the `@ApiPropertyOptional()` decorator. It should use `@ApiProperty()`. ```typescript class TestClass { @Expose() @ApiPropertyOptional() thisIsAStringProp!: string; } ``` -------------------------------- ### Failing: Summary Not Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Illustrates a violation where the 'summary' property in @ApiOperation starts with a lowercase letter. ```typescript class TestClass { @Post("logout") @ApiOperation({ summary: "clears the access-token cookie" // Should start with 'C' }) postLogout(@Res() res: Response) { return; } } ``` -------------------------------- ### Controller Missing ApiTags (Fails) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/controllers-should-supply-api-tags.md This example shows a controller that is missing the @ApiTags decorator, which will cause this rule to fail. ```typescript @Controller("my-controller") class TestClass {} ``` -------------------------------- ### Failing Example: Non-primitive Type without @Type Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example fails because 'members' is a non-primitive type (Date) and has a class-validator decorator (@IsDate) but lacks the required @Type decorator for class-transformer. ```typescript export class CreateOrganizationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) @IsDate() members!: Date; } ``` -------------------------------- ### Failing Example: Non-primitive Array without @Type Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md This example fails because 'members' is an array of non-primitive types (Person | Date) and lacks the @Type decorator, which is required by class-transformer for arrays of non-primitives. ```typescript export class CreateOrganizationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) @IsArray() members!: (Person | Date)[]; } ``` -------------------------------- ### Endpoint Protected by Custom Guard Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-methods-should-be-guarded.md This example illustrates a passing case where an endpoint is protected by a custom guard. Custom guards can be used for more specific or complex authorization logic. ```typescript class TestClass { @Post() @UseGuards(MyCustomGuard("hand-gestures")) public getAll(): Promise { return []; } } ``` -------------------------------- ### Invalid Controller: Singular Name Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md This example shows an invalid controller path that uses a singular resource name, failing the pluralization check. ```typescript @Controller('test') class TestClass { @Get() public getAll() { return []; } } ``` -------------------------------- ### Passing example: @ValidateIf() with @IsDefined() on optional property Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-have-explicit-defined.md Shows a valid pattern where @ValidateIf() is used with @IsDefined() for an optional property. ```typescript export class CreateOrganisationDto { @ValidateIf((o) => !o.id) @IsDefined() @IsString() key?: string } ``` -------------------------------- ### Configuration: Additional Custom Validator Decorators Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md Configure the rule to recognize custom class-validator decorators. This example adds '@IsDateRange' to the list of recognized custom validators. ```json "@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator": [ "error", {additionalCustomValidatorDecorators: ["IsDateRange"]} ] ``` -------------------------------- ### ValidationPipe with forbidUnknownValues: true Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validation-pipe-should-use-forbid-unknown.md This example passes because `forbidUnknownValues` is explicitly set to `true`. Ensure this option is set when configuring your ValidationPipe. ```typescript const validationPipeB = new ValidationPipe({ forbidNonWhitelisted: true, forbidUnknownValues: true, }); ``` -------------------------------- ### Non-Controller/Endpoint Class Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-methods-should-be-guarded.md This example shows a passing case where the class is neither a controller nor an endpoint, thus not requiring a guard. The rule is designed to only apply to API-related methods. ```typescript class TestClass { public getAll(): Promise { return []; } } ``` -------------------------------- ### ValidationPipe with forbidUnknownValues: false Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validation-pipe-should-use-forbid-unknown.md This example fails because `forbidUnknownValues` is explicitly set to `false`. The rule mandates this option to be true for security. ```typescript const validationPipeB = new ValidationPipe({ forbidNonWhitelisted: false, }); ``` -------------------------------- ### Passes: Array with Array and {each: true} Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validate-nested-of-array-should-set-each.md This example also passes, demonstrating that the rule applies correctly to the Array syntax when {each: true} is used with @ValidateNested. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) members!: Array; } ``` -------------------------------- ### Param Matches Route Parameter in @Controller Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/param-decorator-name-matches-route-param.md This example passes because the 'uuid' parameter in the @Param() decorator matches the ':uuid' defined in the @Controller() decorator. ```typescript import { Controller, Get, Param, Request } from "@nestjs/common"; import { ApiOkResponse } from "@nestjs/swagger"; @Controller("custom-bot/:uuid") export class CustomBotController { constructor() {} @Get() @ApiOkResponse({type: CustomBot}) findOne( @Param("uuid") uuid: string, @Request() request: RequestWithUser ): Promise { return this.customBotService.findOne(uuid, request.user.uuid); } } ``` -------------------------------- ### Passes: Array with {each: true} Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validate-nested-of-array-should-set-each.md This example passes because the 'members' property is an array and the @ValidateNested decorator correctly includes the {each: true} option. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) members!: MyClass[]; } ``` -------------------------------- ### ValidationPipe without forbidUnknownValues Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validation-pipe-should-use-forbid-unknown.md This example fails because `forbidUnknownValues` is not explicitly set, and the rule requires it to be true. The default behavior might not be secure. ```typescript const validationPipeB = new ValidationPipe({ forbidNonWhitelisted: true, }); ``` -------------------------------- ### ✅ Correct Usage: app.get() with Regular Services Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-injectable-provided-token.md Demonstrates the correct usage of app.get() for retrieving regular NestJS services and configuration providers. ```typescript const myService = app.get(MyService); const configService = app.get(ConfigService); ``` -------------------------------- ### Configuration: Additional Type Decorators Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validated-non-primitive-property-needs-type-decorator.md Configure the rule to recognize custom type decorators beyond the standard @Type. This example adds '@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator' to the list of recognized decorators. ```json "@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator": [ "error", {additionalTypeDecorators: ["TransformDate"]} ] ``` -------------------------------- ### Incorrect Usage of ApiProperty with oneOf Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-should-have-api-extra-models.md This example shows an incorrect usage where models referenced via `getSchemaPath()` are not registered with `@ApiExtraModels()`, leading to their omission from the OpenAPI schema. ```typescript import { ApiProperty } from '@nestjs/swagger'; import { getSchemaPath } from '@nestjs/swagger'; class MyDto { @ApiProperty({ oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ], }) pet: Cat | Dog; } ``` -------------------------------- ### Fails: Not an array but {each: true} is set Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validate-nested-of-array-should-set-each.md This example fails because the 'members' property is not an array, yet the @ValidateNested decorator incorrectly includes the {each: true} option. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) members!: MyClass; } ``` -------------------------------- ### Valid Controller with Plural Resource Name (kebab-case) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Demonstrates a valid controller path using a plural resource name in kebab-case. ```typescript @Controller('tests') class TestClass { @Get() public getAll() { return []; } } ``` -------------------------------- ### Valid Controller with Multi-Word Resource Name (kebab-case) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Shows a valid controller path for a multi-word resource, correctly formatted in kebab-case. ```typescript @Controller('test-cases') class TestClass { @Get() public getAll() { return []; } } ``` -------------------------------- ### Valid Controller with snake_case Configuration Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Demonstrates a controller and route using snake_case, as specified by a custom configuration. ```typescript // Configuration: { "caseFormat": "snake_case" } @Controller('test_cases') class TestClass { @Get('active_users') public getActiveUsers() { return []; } } ``` -------------------------------- ### Default Configuration for Naming Convention Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md The default configuration enables pluralization checking and enforces kebab-case for paths. ```json { "checkPluralization": true, "caseFormat": "kebab-case" } ``` -------------------------------- ### Passing: Both Summary and Description Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Demonstrates correct capitalization for both 'summary' and 'description' properties in an @ApiOperation decorator. ```typescript class TestClass { @Get() @ApiOperation({ summary: "Get all items", description: "This method returns all available items from the database" }) public getAll(): Promise { return []; } } ``` -------------------------------- ### Extend ESLint Recommended and No Swagger Rules Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md Extend the recommended ruleset and optionally disable all swagger rules if you do not use swagger by adding `flatNoSwagger` after the recommended rule set. ```javascript // all the other config extends: [ "plugin:@darraghor/nestjs-typed/recommended", "plugin:@darraghor/nestjs-typed/no-swagger" ], // more config ``` -------------------------------- ### Configure ESLint Classic Config Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md For ESLint 8, use the `classicConfig` export to integrate the plugin into your old-style ESLint configuration. ```javascript import {classicPlugin} from "@darraghor/eslint-plugin-nestjs-typed"; module.exports = { plugins: [classicPlugin], }; ``` -------------------------------- ### Configure ESLint Flat Config Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/README.md Update your flat ESLint configuration to include the plugin and its recommended rule set. Ensure the TypeScript parser is also configured. ```typescript import eslintNestJs from "@darraghor/eslint-plugin-nestjs-typed"; // ... and all your other imports export default tseslint.config( eslint.configs.recommended, tseslint.configs.strictTypeChecked, tseslint.configs.stylisticTypeChecked, { languageOptions: { globals: { ...globals.node, ...globals.jest, }, parser, ecmaVersion: 2022, sourceType: "module", parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname, }, }, }, eslintNestJs.configs.flatRecommended // This is the recommended ruleset for this plugin ); ``` -------------------------------- ### Enable use-correct-endpoint-naming-convention Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md To enable this rule, add it to your ESLint configuration under the rules section with the desired severity. ```json { "rules": { "@darraghor/nestjs-typed/use-correct-endpoint-naming-convention": "error" } } ``` -------------------------------- ### Incorrect: Direct Instantiation Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Avoid direct instantiation of dependencies within the class body. Use dependency injection instead. ```typescript import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class CatService { private logger = new Logger(); // ❌ Direct instantiation } ``` -------------------------------- ### Valid Decorator Usage (Passes) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/no-duplicate-decorators.md Demonstrates correct usage where each property or class is decorated only once. ```typescript @DiscoverDecorator() class MyClass { @DiscoverDecorator() myProperty: string; } ``` -------------------------------- ### Provider Failing Due to Missing Factory Parameter Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/provided-injected-should-match-factory-parameters.md This provider fails the rule because `SecondService` is used as a parameter in the `useFactory` function but is not included in the `inject` array. This can be ignored if `SecondService` is marked as `@Global()`. ```typescript export const MyOtherInjectableProvider: Provider = { provide: MyOtherInjectable, useFactory: async ( config: MyService, secondService: SecondService ): Promise => { return new MyOtherInjectable(); }, inject: [MyService], }; ``` -------------------------------- ### ✅ Correct Usage: APP_* Tokens in Module Providers Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-injectable-provided-token.md Correctly register global providers like APP_GUARD, APP_PIPE, APP_FILTER, and APP_INTERCEPTOR within the 'providers' array of a module. This is the intended way to use these special tokens. ```typescript @Module({ providers: [ { provide: APP_GUARD, useClass: AuthGuard, }, { provide: APP_PIPE, useClass: ValidationPipe, }, { provide: APP_FILTER, useClass: HttpExceptionFilter, }, { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor, }, ], }) export class AppModule {} ``` -------------------------------- ### Configure Rule Options Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-matches-property-optionality.md Customize the behavior of the `api-property-matches-property-optionality` rule. By default, `checkRedundantRequired` is enabled. ```json { "checkRedundantRequired": true // default: true } ``` ```json { "@darraghor/nestjs-typed/api-property-matches-property-optionality": [ "error", { "checkRedundantRequired": false } ] } ``` -------------------------------- ### Incorrect: Instantiation in Constructor Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Dependencies should not be instantiated directly within the constructor. They should be injected. ```typescript import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class CatService { logger; constructor() { this.logger = new Logger(); // ❌ Instantiation in constructor } } ``` -------------------------------- ### Custom Configuration: Use snake_case Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Configure the rule to enforce snake_case for paths, while still enabling pluralization checks. ```json { "@darraghor/nestjs-typed/use-correct-endpoint-naming-convention": [ "error", { "checkPluralization": true, "caseFormat": "snake_case" } ] } ``` -------------------------------- ### Invalid Controller: camelCase Path Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md An invalid controller path that uses camelCase instead of the expected kebab-case format. ```typescript @Controller('testCases') class TestClass { @Get() public getAll() { return []; } } ``` -------------------------------- ### Incorrect: Direct Require Call Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Avoid direct calls to 'require' for dependencies within the class. Use dependency injection. ```typescript import { Injectable } from '@nestjs/common'; @Injectable() export class CatService { private logger = require('bunyan'); // ❌ Direct require call } ``` -------------------------------- ### Correct Usage of ApiProperty with oneOf and ApiExtraModels Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-property-should-have-api-extra-models.md Demonstrates correct ways to register models with `@ApiExtraModels()` when using `oneOf` with `getSchemaPath()`. This ensures models are included in the OpenAPI schema. ```typescript import { ApiProperty, ApiExtraModels } from '@nestjs/swagger'; import { getSchemaPath } from '@nestjs/swagger'; // Option 1: Add ApiExtraModels to the DTO @ApiExtraModels(Cat, Dog) class MyDto { @ApiProperty({ oneOf: [ { $ref: getSchemaPath(Cat) }, { $ref: getSchemaPath(Dog) }, ], }) pet: Cat | Dog; } ``` ```typescript import { ApiProperty, ApiExtraModels } from '@nestjs/swagger'; import { getSchemaPath } from '@nestjs/swagger'; // Option 2: Add ApiExtraModels to the controller @ApiExtraModels(Cat, Dog) @Controller('pets') class PetController { // ... } ``` ```typescript import { ApiProperty, ApiExtraModels } from '@nestjs/swagger'; import { getSchemaPath } from '@nestjs/swagger'; // Option 3: Use the models directly as return types @ApiOkResponse({ type: Cat }) someMethod(): Cat { // ... } ``` -------------------------------- ### Failing: Description Not Capitalized Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-operation-summary-description-capitalized.md Shows an instance where the 'description' property in @ApiOperation begins with a lowercase letter. ```typescript class TestClass { @Get() @ApiOperation({ description: "returns all items" // Should start with 'R' }) public getAll(): Promise { return []; } } ``` -------------------------------- ### Valid Route with Parameters (Ignored in Validation) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Illustrates a valid route that includes parameters, which are ignored by the naming convention validation. ```typescript @Controller('tests') class TestClass { @Get('some-param/:someParam') public getByParam(@Param('someParam') param) { return param; } } ``` -------------------------------- ### Configure ESLint Rule with Additional Decorators Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-are-whitelisted.md Configure the `all-properties-are-whitelisted` rule in your ESLint configuration to include custom decorators that should be treated as validation decorators. ```javascript export default [ { rules: { "@darraghor/nestjs-typed/all-properties-are-whitelisted": [ "error", { additionalDecorators: ["IsValidLoginIdentifier", "MyCustomValidator"] } ] } } ]; ``` -------------------------------- ### ✅ Correct Usage: @Inject() with Regular Tokens Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-injectable-provided-token.md Shows the proper use of the @Inject() decorator with standard service tokens and custom string tokens for dependency injection. ```typescript @Injectable() class MyService { constructor( @Inject(ConfigService) private config: ConfigService, @Inject('CUSTOM_TOKEN') private customProvider: any, ) {} } ``` -------------------------------- ### Provider Failing Due to Extra Injection Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/provided-injected-should-match-factory-parameters.md This provider fails the rule because `SecondService` is listed in the `inject` array but not used as a parameter in the `useFactory` function. This often indicates a developer error. ```typescript export const MyOtherInjectableProvider: Provider = { provide: MyOtherInjectable, useFactory: async (config: MyService): Promise => { return new MyOtherInjectable(); }, inject: [MyService, SecondService], }; ``` -------------------------------- ### Custom Configuration: Disable Pluralization Checking Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md Configure the rule to disable pluralization checks while maintaining kebab-case formatting for controller paths. ```json { "@darraghor/nestjs-typed/use-correct-endpoint-naming-convention": [ "error", { "checkPluralization": false, "caseFormat": "kebab-case" } ] } ``` -------------------------------- ### Invalid Route: camelCase Instead of kebab-case Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md An invalid route path that uses camelCase when kebab-case is expected. ```typescript @Controller('tests') class TestClass { @Get('getByParam/:someParam') public getByParam(@Param('someParam') param) { return param; } } ``` -------------------------------- ### ❌ Incorrect Usage: app.get() with APP_* Tokens Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-injectable-provided-token.md Avoid using app.get() with special NestJS tokens such as APP_GUARD, APP_PIPE, APP_FILTER, and APP_INTERCEPTOR. These operations will result in runtime errors. ```typescript const guard = app.get(APP_GUARD); const pipe = app.get(APP_PIPE); const filter = app.get(APP_FILTER); const interceptor = app.get(APP_INTERCEPTOR); ``` -------------------------------- ### Invalid Controller: PascalCase Path Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-correct-endpoint-naming-convention.md An invalid controller path that uses PascalCase, which does not conform to standard REST API naming conventions. ```typescript @Controller('TestCases') class TestClass { @Get() public getAll() { return []; } } ``` -------------------------------- ### Incorrect: Using Imported Module Directly Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Do not use imported modules directly as dependencies. Inject them via the constructor. ```typescript import bunyan from 'bunyan'; import { Injectable } from '@nestjs/common'; @Injectable() export class CatService { private logger = bunyan; // ❌ Using imported module directly } ``` -------------------------------- ### Valid @Injectable Provider in Module Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/injectable-should-be-provided.md Demonstrates a correct way to include an @Injectable class in a module's providers using direct array assignment. This pattern is recognized by the rule. ```typescript import { Module } from '@nestjs/common'; @Module({ imports: [], providers: [MyProvider], }) export class ProviderArrayModule {} ``` -------------------------------- ### Module with Sorted Imports Array Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/sort-module-metadata-arrays.md This code passes the rule because all arrays, including `imports`, are in alphabetical ascending order. ```typescript @Module({ imports: [ AuthzModule, CoreModule, DatabaseModule, OpenTelemetryModule.forRoot({ metrics: { hostMetrics: true, apiMetrics: { enable: true, }, }, }), UserInternalModule, ], controllers: [AController, BController], providers: [AProvider, BProvider], }) export class MainModule {} ``` -------------------------------- ### Configure Sort Module Metadata Arrays Rule Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/sort-module-metadata-arrays.md Add the rule to your ESLint configuration to enable sorting of module metadata arrays. You can specify a locale for sorting if the default 'en-US' is not suitable. ```json "@darraghor/nestjs-typed/sort-module-metadata-arrays": [ "warn", { locale: "en-AU" }, ] ``` -------------------------------- ### Factory Provider with Unsorted Inject Array Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/sort-module-metadata-arrays.md This code passes the rule even though the `inject` array is not alphabetically sorted. The `inject` array order must match the `useFactory` function parameters and is therefore not sorted by this rule. ```typescript @Module({ providers: [ { provide: 'EXAMPLE_PROVIDER', useFactory: (bProvider: BProvider, aProvider: AProvider): unknown => { return new WhatEver(); }, // inject array is NOT sorted - it must match the useFactory parameters inject: [BProvider, AProvider], } ] }) export class MainModule {} ``` -------------------------------- ### Module with Unsorted Imports Array Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/sort-module-metadata-arrays.md This code fails the rule because the `imports` array is not in alphabetical ascending order. ```typescript @Module({ imports: [ CoreModule, DatabaseModule, OpenTelemetryModule.forRoot({ metrics: { hostMetrics: true, apiMetrics: { enable: true, }, }, }), UserInternalModule, AuthzModule, ], controllers: [AController, BController], providers: [AProvider, BProvider], }) export class MainModule {} ``` -------------------------------- ### Correct: Injected via Constructor Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Dependencies should be injected directly through the class constructor using TypeScript's parameter properties. ```typescript import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class CatService { constructor(private logger: Logger) {} } ``` -------------------------------- ### DTO Passing - All Properties Decorated Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-are-whitelisted.md This DTO passes the rule because all its properties are decorated with either a class-validator decorator or `@Allow()`. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) members!: MyClass[]; @ApiProperty() @Allow() otherProperty!: MyClass; @ApiProperty() @IsString() someStringProperty!: string; } ``` -------------------------------- ### DTO Failing - Missing Validation Decorator Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-are-whitelisted.md This DTO fails the rule because the `otherProperty` is missing a validation decorator, which is likely a mistake. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested({each: true}) members!: MyClass[]; @ApiProperty() otherProperty!: MyClass; } ``` -------------------------------- ### Configure additional decorators in ESLint config Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-have-explicit-defined.md Specify custom decorator names to be recognized by the rule. This is useful for decorators registered with `class-validator`'s `registerDecorator`. ```javascript export default [ { rules: { "@darraghor/nestjs-typed/all-properties-have-explicit-defined": [ "error", { additionalDecorators: ["IsValidLoginIdentifier", "MyCustomValidator"] } ] } } ]; ``` -------------------------------- ### Correct: Assigned from Injected Parameter Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Dependencies can be assigned to class properties if they are first injected as constructor parameters. ```typescript import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class CatService { private logger: Logger; constructor(logger: Logger) { this.logger = logger; } } ``` -------------------------------- ### DTO Passing - Custom Decorator with Configuration Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/all-properties-are-whitelisted.md This DTO passes when the rule is configured to recognize `IsValidLoginIdentifier` as a valid decorator. ```typescript export class LoginDto { @IsValidLoginIdentifier() identifier: string; @IsString() password: string; } ``` -------------------------------- ### Allowed: Primitive Constants Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Defining primitive constants or string literals directly within the class is permitted. ```typescript import { Injectable } from '@nestjs/common'; @Injectable() export class CatService { private readonly maxRetries = 3; // ✅ Primitive constants are OK private name = 'CatService'; // ✅ String literals are OK } ``` -------------------------------- ### Correct Enum Property with ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-enum-property-best-practices.md Use `enum` and `enumName` in `ApiProperty` for correct Open API enum generation. This is the recommended approach. ```typescript class TestClass { @ApiPropertyOptional({enum: MyEnum, enumName: "MyEnum"}) thisIsAnEnumProp?: MyEnum; } ``` -------------------------------- ### Invalid @Injectable Provider Assignment (Variable Reference) Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/injectable-should-be-provided.md Illustrates an assignment pattern that the rule does not support. It will not follow variable references to check providers, potentially leading to runtime errors if not manually verified. ```typescript import { Module } from '@nestjs/common'; const providers = [ExampleProviderIncludedInModule]; @Module({ imports: [], providers: providers, }) export class ProviderArrayModule {} ``` -------------------------------- ### Passing API Method with Explicit API Response Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-method-should-specify-api-response.md This code snippet demonstrates a passing case where an API method correctly specifies its response using @ApiResponse and @ApiBadRequestResponse decorators. ```typescript class TestClass { @Get() @ApiResponse({status: 200, type: String}) @ApiBadRequestResponse({description: "Bad Request"}) public getAll(): Promise { return []; } } ``` -------------------------------- ### Disabling Rule for Files Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Disable the entire rule for a file by adding a comment at the top, useful for utility classes or files not using NestJS DI. ```typescript /* eslint-disable @darraghor/nestjs-typed/use-dependency-injection */ // Your code here... ``` -------------------------------- ### Failing API Method Missing API Response Decorators Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-method-should-specify-api-response.md This code snippet represents a failing case where an API method lacks the necessary @ApiResponse decorators, violating the rule. ```typescript class TestClass { @Get() public getAll(): Promise { return []; } } ``` -------------------------------- ### Provide Enum Name in ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-enum-property-best-practices.md Always specify `enumName` when using `enum` in `ApiProperty`. Omitting it leads to poorly named enums in Open API specifications. ```typescript class TestClass { @ApiPropertyOptional({enum: MyEnum}) thisIsAnEnumProp?: MyEnum; } ``` -------------------------------- ### Match Enum Name and Type in ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-enum-property-best-practices.md Ensure that the `enumName` value in `ApiProperty` exactly matches the enum type specified. Mismatches can result in duplicate or incorrect enum definitions. ```typescript class MyClass { @ApiProperty({enumName: "MyEnumTYPO", enum: MyEnum}) public myProperty!: MyEnum; } ``` -------------------------------- ### ❌ Incorrect Usage: @Inject() with APP_* Tokens Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-injectable-provided-token.md Do not use the @Inject() decorator with special NestJS tokens like APP_GUARD, APP_PIPE, APP_FILTER, and APP_INTERCEPTOR. This will lead to runtime failures. ```typescript @Injectable() class MyService { // These will fail at runtime constructor( @Inject(APP_GUARD) private guard: any, @Inject(APP_PIPE) private pipe: any, @Inject(APP_FILTER) private filter: any, @Inject(APP_INTERCEPTOR) private interceptor: any ) {} } ``` -------------------------------- ### Avoid Redundant Type in ApiProperty Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/api-enum-property-best-practices.md Do not include `type` in `ApiProperty` when specifying `enum`. This was necessary in older versions but is now redundant and can cause issues. ```typescript class TestClass { @ApiPropertyOptional({type: MyEnum, enum: MyEnum, enumName: "MyEnum"}) thisIsAnEnumProp?: MyEnum; } ``` -------------------------------- ### Disabling Rule for Specific Lines Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Use the eslint-disable-next-line directive to ignore the rule for specific lines where direct instantiation is necessary. ```typescript import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class CatService { // eslint-disable-next-line @darraghor/nestjs-typed/use-dependency-injection private logger = new Logger(); } ``` -------------------------------- ### Passes: Not an array and {each: false/omitted} Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/validate-nested-of-array-should-set-each.md This scenario passes because the 'members' property is not an array, and therefore, the {each: true} option is not required for @ValidateNested. ```typescript export class CreateOrganisationDto { @ApiProperty({type: Person, isArray: true}) @ValidateNested() members!: MyClass; } ``` -------------------------------- ### Allowed: Object Literals Source: https://github.com/darraghoriordan/eslint-plugin-nestjs-typed/blob/main/src/docs/rules/use-dependency-injection.md Defining object literals directly within the class is permitted. ```typescript import { Injectable } from '@nestjs/common'; @Injectable() export class CatService { private config = { debug: true }; // ✅ Object literals are OK } ```