nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.69k stars 7.63k forks source link

MODULE_OPTIONS_TOKEN can not be resolved in Pipe #13126

Closed macure closed 9 months ago

macure commented 9 months ago

Is there an existing issue for this?

Current behavior

I created a dynamic module, like it was explained in the documentation by using a ConfigurableModuleBuilder and ConfigurableModuleClass

I'm getting this error when trying to inject the configuration token into a pipe: Nest can't resolve dependencies of the ProcessImagePipe (?). Please make sure that the argument CONFIGURABLE_MODULE_OPTIONS[02271392a116315423ae3] at index [0] is available in the AppModule context.

image.module-definitions.ts

export interface ImageModuleOptions {
  size: string;
}

import { ConfigurableModuleBuilder } from '@nestjs/common';

export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
  new ConfigurableModuleBuilder<ImageModuleOptions>().build();

image.module.ts

import { Module } from '@nestjs/common';
import { ProcessImagePipe } from './process-image.pipe';
import { ConfigurableModuleClass } from './image.module-definitions';
import { ImageService } from './image.service';

@Module({
  providers: [ProcessImagePipe, ImageService],
  exports: [ProcessImagePipe, ImageService],
})
export class ImageModule extends ConfigurableModuleClass {}

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ImageModule } from './image/image.module';

@Module({
  imports: [
    ImageModule.register({
      size: 'large',
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

app.controller.ts

import { Controller, Get, UsePipes } from '@nestjs/common';
import { AppService } from './app.service';
import { ProcessImagePipe } from './image/process-image.pipe';
import { ImageService } from './image/image.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly imageService: ImageService,
  ) {}

  @Get()
  @UsePipes(ProcessImagePipe)
  getHello(): string {
    this.imageService.log();
    return this.appService.getHello();
  }
}

That being said, I was perfectly fine injecting the same token in image.service.ts and it works without any errors. It's just when I try to inject it in the pipe.

What works here is if I inject ImageService, which already has MODULE_OPTIONS_TOKEN injected... All works... no errors.

Does any one now if this is a desired behavior? Why wouldn't we want to inject tokens in the Pipe directly?

Minimum reproduction code

https://stackblitz.com/edit/nestjs-typescript-starter-t3bgqu

Steps to reproduce

Just run (in case this hasn't been done for you already)

npm install && npm run start

Then check the error log in the console

Expected behavior

I expected to have access to injected token inside a pipe.

In the context of the provided code: I expect to see the output of:

console.log('Pipe:', this.options);

Package

Other package

No response

NestJS version

10.1.18

Packages versions

{
  "name": "nest-typescript-starter",
  "private": true,
  "version": "1.0.0",
  "description": "Nest TypeScript starter repository",
  "license": "MIT",
  "scripts": {
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/jest/bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.8.1"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.1",
    "@nestjs/schematics": "^10.0.1",
    "@nestjs/testing": "^10.0.0",
    "@swc/cli": "^0.1.62",
    "@swc/core": "^1.3.64",
    "@types/express": "^4.17.17",
    "@types/jest": "^29.5.2",
    "@types/node": "^20.3.1",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^5.59.11",
    "@typescript-eslint/parser": "^5.59.11",
    "eslint": "^8.42.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-plugin-prettier": "^4.2.1",
    "jest": "^29.5.0",
    "prettier": "^2.8.8",
    "source-map-support": "^0.5.21",
    "supertest": "^6.3.3",
    "ts-jest": "^29.1.0",
    "ts-loader": "^9.4.3",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.1.3"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Node.js version

v18.18.0

In which operating systems have you tested?

Other

Tested on several different NestJS and Node versions with same result.

I hope you can shed some light ...

Thank you

kamilmysliwiec commented 9 months ago

Thank you for taking the time to submit your report! From the looks of it, this could be better discussed on our Discord. If you haven't already, please join here and send a new post in the #⁠ 🐈 nestjs-help forum. Make sure to include a link to this issue, so you don't need to write it all again. We have a large community of helpful members, who will assist you in getting this to work.