instantcommerce / next-api-decorators

Collection of decorators to create typed Next.js API routes, with easy request validation and transformation.
https://next-api-decorators.vercel.app
MIT License
409 stars 29 forks source link

Validation pipe doesn't work #560

Closed fake364 closed 1 year ago

fake364 commented 1 year ago

Hi, I've just noticed that validation pipe doesn't work at all though it validates correctly if I use validate(...) from class-validator. Currently The object {"postId":"7d2dc33e-2bb2-430d-9603-e463903cdca1","text":" ","userId":110} is Passed successfuly, and no logs in transform callback Here are my code samples api controller

import {
  Body,
  createHandler,
  Post,
  Res,
  ValidationPipe
} from 'next-api-decorators';
import CommentEntity from '../../../../src/common/classes/commentEntity/CommentEntity';
import { WithSessionAuth } from '../../checkSession';
import PostsCommentsService from '../../../../src/common/backend/services/postsCommentsService/PostsCommentsService';
import type { NextApiResponse } from 'next';
import { StatusCodes } from 'http-status-codes';

class CommentsHandler {
  @WithSessionAuth()
  @Post()
  async createComment(
    @Body(ValidationPipe) { text, userId, postId }: CommentEntity,
    @Res() res: NextApiResponse
  ) {
    try {
      await PostsCommentsService.createComment(text, postId, userId);
      return;
    } catch (e) {
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: e });
    }
  }
}

export default createHandler(CommentsHandler);

CommentEntity

import { IsNotEmpty, IsNumber, IsString, MaxLength } from 'class-validator';
import { Transform, TransformFnParams } from 'class-transformer';

export default class CommentEntity {
  @IsString()
  @Transform(({ value }: TransformFnParams) => {
    console.log('TRANSFORMING', value);
    return value?.trim();
  })
  @IsNotEmpty()
  @MaxLength(400)
  text: string;

  @IsString()
  postId: string;

  @IsNumber()
  userId: number;
}

Node: 14.17.1 tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "es6",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "strictPropertyInitialization": false
  },
  "include": ["next-env.d.ts", "(pages|src)/**/*.ts", "(pages|src)/**/*.tsx"],
  "exclude": ["node_modules", "faketerest-pager"]
}

package.json

{
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "analyze": "cross-env ANALYZE=true next build",
    "test": "jest --passWithNoTests --coverage --forceExit"
  },
  "dependencies": {
    "@react-icons/all-files": "^4.1.0",
    "@socket.io/postgres-adapter": "^0.3.0",
    "@tailwindcss/line-clamp": "^0.4.2",
    "@types/crypto-js": "^4.1.1",
    "@types/lodash": "4.14.178",
    "@types/react-motion": "0.0.32",
    "axios": "^0.27.2",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.13.2",
    "clsx": "^1.1.1",
    "cookie": "^0.5.0",
    "crypto-js": "^4.1.1",
    "faketerest-utilities": "1.0.13",
    "formidable": "^2.0.1",
    "formik": "^2.2.9",
    "image-size": "^1.0.2",
    "jwt-decode": "^3.1.2",
    "lodash": "4.17.21",
    "next": "12.3.4",
    "next-api-decorators": "2.0.0",
    "next-redux-wrapper": "^7.0.5",
    "next-translate": "^1.5.0",
    "nprogress": "^0.2.0",
    "pg": "^8.8.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-icons": "^4.3.1",
    "react-infinite-scroll-component": "6.1.0",
    "react-lines-ellipsis": "^0.15.3",
    "react-redux": "^8.0.2",
    "redis": "^4.4.0",
    "redux": "^4.2.0",
    "redux-devtools-extension": "^2.13.9",
    "redux-persist": "^6.0.0",
    "redux-thunk": "^2.4.1",
    "reflect-metadata": "^0.1.13",
    "sequelize": "^6.19.0",
    "sequelize-typescript": "^2.1.3",
    "sharp": "^0.29.3",
    "socket.io": "^4.5.3",
    "socket.io-client": "4.5.3",
    "tailwindcss": "3.1.6",
    "tailwindcss-animation-delay": "^1.0.7",
    "uuidv4": "^6.2.13",
    "yup": "^0.32.11"
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/plugin-proposal-decorators": "^7.18.10",
    "@babel/plugin-transform-runtime": "^7.16.7",
    "@babel/preset-env": "^7.16.7",
    "@babel/preset-react": "^7.16.7",
    "@babel/preset-typescript": "^7.16.7",
    "@next/bundle-analyzer": "^12.0.7",
    "@testing-library/react": "13.3.0",
    "@testing-library/react-hooks": "8.0.1",
    "@types/cookie": "^0.5.1",
    "@types/enzyme": "^3.10.11",
    "@types/jest": "^27.4.0",
    "@types/jsonwebtoken": "^8.5.8",
    "@types/react": "17.0.2",
    "@typescript-eslint/eslint-plugin": "^5.9.0",
    "@typescript-eslint/parser": "^5.9.0",
    "@wojtekmaj/enzyme-adapter-react-17": "^0.6.6",
    "autoprefixer": "^10.4.1",
    "babel-jest": "^27.4.6",
    "babel-plugin-parameter-decorator": "^1.0.16",
    "babel-plugin-transform-typescript-metadata": "^0.3.2",
    "cross-env": "^7.0.3",
    "enzyme": "^3.11.0",
    "enzyme-to-json": "^3.6.2",
    "eslint": "^8.6.0",
    "eslint-plugin-react": "^7.28.0",
    "fs": "0.0.1-security",
    "glob": "^7.2.0",
    "http-status-codes": "^2.2.0",
    "jest": "^27.4.7",
    "jest-environment-jsdom": "^28.1.3",
    "jsdom": "19.0.0",
    "jsdom-global": "3.0.2",
    "pg-hstore": "^2.3.4",
    "postcss": "^8.4.5",
    "postcss-cli": "^9.1.0",
    "prettier": "2.5.1",
    "redux-mock-store": "1.5.4",
    "sass": "^1.45.2",
    "ts-jest": "^27.1.2",
    "typescript": "^4.5.4"
  }
}

And yes, I installed all required packages :)

ggurkal commented 1 year ago

Hi @fake364

Can't replicate the issue you're having. Please provide a minimum reproducible repo.

fake364 commented 1 year ago

@ggurkal Hi, thank you for response, and sorry for long delay I could reproduce this and made minimal reproducible example https://github.com/fake364/pipe-error-repro I noticed that while using SWC there weren't such problems like this one, but after adding babel.config.js and additional libraries the issue seems became reproducible

ggurkal commented 1 year ago

Hi @fake364

Sorry for the late reply.

The problems seems to be related to your babel config. Please follow the guideline here: https://nextjs.org/docs/pages/building-your-application/configuring/babel

Feel free to reopen the issue if you encounter a problem related to this.