typestack / routing-controllers

Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage in Express / Koa using TypeScript and Routing Controllers Framework.
MIT License
4.41k stars 394 forks source link

question: @Param not type casted #1157

Open NicholasMKim opened 1 year ago

NicholasMKim commented 1 year ago

I was trying to... Context:

The problem: After migrating to sst @Param doesn't cast id: number into number.

app.ts

import "reflect-metadata";
import { createExpressServer } from "routing-controllers";
import serverlessExpress from "@vendia/serverless-express";
import { APIGatewayProxyHandlerV2 } from "aws-lambda";

const app = createExpressServer({
  classTransformer: true,
  controllers: [/** controllers */]
});

export const handler: APIGatewayProxyHandlerV2 = (event, context) => {
  const instance = serverlessExpress({ app });
  return instance(event, context, () => {
    console.log("Server started");
  });
};

oneOfTheControllers.ts

@JsonController("/api/v1")
export class ListingController {
  @Get("/listing/agent-team/:agentTeamId")
  @OnUndefined(404)
  @OnNull(404)
  async getListingsByAgentTeamId(
    @CurrentUser() user: any,
    @Param("agentTeamId") agentTeamId: number
  ) {
    // agentTeamId is string
    authValidator(Number(agentTeamId), user, "agentTeamId");
    const listings = await ListingModel.getListingsByAgentTeamId(
      user.agentTeamId
    );
    return listings;
  }
}
attilaorosz commented 1 year ago

Well this indeed seems weird. Could you setup a repro repo so I can debug?

NicholasMKim commented 1 year ago

Here is the link for testing and it acts the same.

https://github.com/mkim871/sst-testing/blob/4640f178b68f481757c17231062c7f4f7fda702d/packages/functions/src/app.ts#L26

attilaorosz commented 1 year ago

Is there a chance you are missing "emitDecoratorMetadata": true, from your tsconfig.json?

NicholasMKim commented 1 year ago

I think that's not the issue. My main project has "emitDecoratorMetadata": true and I just tested the testing repo with that too 🥲. Do you know which function is responsible for class-transformer?

attilaorosz commented 1 year ago

Unfortunately I have no experience with sst. I tried your repo locally, adding emitDecoratorMetadata: true and it worked as intended. The transformation happens here: https://github.com/typestack/routing-controllers/blob/90ebb6a11e0a1d2f9f9da143c034576cdb564fa6/src/ActionParameterHandler.ts#LL215C21-L215C21

NicholasMKim commented 1 year ago
Screenshot 2023-06-13 at 11 33 18 AM

When I log the targetname, it is undefined. Can versions be a problem? Such as ts, node or class-transformer?

attilaorosz commented 1 year ago

Could you try to log the values here? https://github.com/typestack/routing-controllers/blob/90ebb6a11e0a1d2f9f9da143c034576cdb564fa6/src/metadata/ParamMetadata.ts#LL123C1-L123C1

To see of explicitType is set or ParamTypes is resolved correctly.

NicholasMKim commented 1 year ago

Screenshot 2023-06-13 at 7 47 27 PM

What have I done wrong 😂. btw, Much appreciated for helping. You are the legend!

attilaorosz commented 1 year ago

Well it seems like emitDecoratorMetadata is not set so you are not getting type information. Are you sure it is set correctly?

NicholasMKim commented 1 year ago

It seems right to me https://github.com/mkim871/sst-testing/blob/main/packages/functions/tsconfig.json

attilaorosz commented 1 year ago

Sorry for the very long delay. Did you find a solution to this? The tsconfig.json indeed looks ok to me.

nick-paloma commented 11 months ago

Just ran into this issue as well. tsconfig.json was:

{
  "extends": "@cappsule/tsconfig/node.json",
  "include": ["src", "./db/**/*", "./scripts/**/*", "./generated/**/*"],

  "exclude": [
    "node_modules",
    "./coverage",
    "./dist",
    "__tests__",
    "jest.config.js"
  ],
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  }
}

The problem was we were dumping it into prisma which expected a number, a simple Number(param) fixed it but yea not sure what the cause is.

Should note that it worked in dev mode so something happens during compile to not cast it i guess.

attilaorosz commented 11 months ago

What do you use to compile typescript? I know we had issues with esbuild and type casting from decorators.

nick-paloma commented 10 months ago

good question, unless I'm mistaken, we're using swc and this is the .swcrc

{
  "env": {
    "target": {
      "node": 18
    }
  },
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "decorators": true
    }
  },
  "module": {
    "type": "commonjs"
  },
  "sourceMaps": "inline"
}
attilaorosz commented 10 months ago

You have reflect-metadata imported, right?

nick-paloma commented 10 months ago

yea and its in the dist too "reflect-metadata": "^0.1.13",

attilaorosz commented 10 months ago

Could you try to make a simple repro repo for this so I can debug it further?

nick-paloma commented 10 months ago

sure mate, ill ping here when its done

nick-paloma commented 10 months ago

heres the repo

Prod:

yarn && yarn build && yarn start:prod

Dev:

yarn && yarn start:dev

Navigate to: http://localhost:9876/test/1

On prod it should give:

{"type":"string"}

And on dev it'll be:

{"type":"number"}
attilaorosz commented 10 months ago

It seems like you are missing some config in .swcrc. Could you try adding

"transform": {
  "legacyDecorator": true,
  "decoratorMetadata": true
}

into the "jsc" block?

nick-paloma commented 10 months ago

That got it for me. Can't believe I missed that one. Although it might not have been the case for OP

Thanks much

engr-mervin commented 4 weeks ago

Any updates regarding this? I had the same error where @Param arguments are not being type-casted, tried to debug and I'm seeing param.targetName to be empty strings

attilaorosz commented 3 weeks ago

@engr-mervin could you provide more context or a repro repo?

engr-mervin commented 3 weeks ago

Hi, after a day of debugging, it turns out that it was not a problem with routing-controllers itself, but it's because I'm using tsx which does not support decorators. I moved to tsc with watch instead, and everything is working. Thanks