lukeautry / tsoa

Build OpenAPI-compliant REST APIs using TypeScript and Node
MIT License
3.44k stars 492 forks source link

Cannot upgrade from 5.x.x to 6.x.x using Express, Prisma and Multer uploads #1651

Open RomainGueffier opened 1 month ago

RomainGueffier commented 1 month ago

Hi,

Tsoa 6 CLI spec-and-routes is still crashing after multiple attempts to upgrade on each minor version since version 6. Some issues about this seems similar but have been closed as completed, however I still encounter those issues. All is working correctly in Tsoa 5

Prisma errors:

There was a problem resolving type of 'Agency'.
Generate routes error.
TypeError: Cannot read properties of undefined (reading 'kind')
at Object.isEnumMember (/home/romain-g/customers-sites/node_modules/typescript/lib/typescript.js:30442:15)
at TypeResolver.calcRefTypeName (/home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:549:20)
at TypeResolver.calcTypeReferenceTypeName (/home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:712:34)
at TypeResolver.calcTypeName (/home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:629:25)
at /home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:663:64
at Array.map (<anonymous>)
at TypeResolver.calcTypeName (/home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:663:47)
at /home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:635:43
at Array.map (<anonymous>)
at TypeResolver.calcTypeName (/home/romain-g/customers-sites/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:632:41)

Multer errors:

.tsoa/routes.ts:2638:56 - error TS2353: Object literal may only specify known properties, and '"multiple"' does not exist in type 'Field'.
  upload.fields([{"name":"file","maxCount":1,"multiple":false}]),

Other errors:

.tsoa/routes.ts:2479:21 - error TS2741: Property 'name' is missing in type '{ in: string; required: true; ref: string; }' but required in type 'ParameterSchema'.
  undefined: {"in":"body","required":true,"ref":"AgentFeesBody"},

Sorting

Expected Behavior

tsoa spec-and-routes to complete without typescript errors.

Ideally:

import type { Agency } from '@prima/client'

export type AgencyJoinActivityResponse = Promise<{ data: Agency }>

@Route('agencies')
@Tags('Agency')
@Security('jwt_token')
@SuccessResponse('201', 'Success')
@Response<AuthErrorResponse>(401, 'Unauthorized')
@Response<AuthErrorResponse>(403, 'Forbidden Access')
@Response<ValidateError>(422, 'ValidationError')
@Response<ServerErrorResponse>(500, 'Internal Error')
export class AgencyController extends Controller {
  @Post()
  @SuccessResponse(201, 'Created')
  async createOneAgency(
    @Request() req: Express.Request,
    @FormField() name: string,
    @FormField() website: string,
    @FormField() description: string,
    @FormField() address: string,
    @UploadedFile() file?: Express.Multer.File
  ): AgencyJoinActivityResponse {
    // ....code
  }
}

Current Behavior

To bypass typescript errors, I had to write:

import type { Agency } from '@prima/client'

export type AgencyJoinActivityResponse = Promise<{ data: {
  name: string
  description: string
  // rewrite prisma types and lost schema sync ! 🔴
}}>

@Route('agencies')
@Tags('Agency')
@Security('jwt_token')
@SuccessResponse('201', 'Success')
@Response<AuthErrorResponse>(401, 'Unauthorized')
@Response<AuthErrorResponse>(403, 'Forbidden Access')
@Response<ValidateError>(422, 'ValidationError')
@Response<ServerErrorResponse>(500, 'Internal Error')
export class AgencyController extends Controller {
  @Post()
  @SuccessResponse(201, 'Created')
  async createOneAgency(
    @Request() req: Express.Request,
    @FormField() name: string,
    @FormField() website: string,
    @FormField() description: string,
    @FormField() address: string,
    @UploadedFile() file?: Express.Multer.File
  ): AgencyJoinActivityResponse {
    // ....code
  }
}

Possible Solution

--

Steps to Reproduce

Run tsoa spec and routes

Context (Environment)

Version of the library: 6.x.x, in example 6.4.0 Version of NodeJS: 18-22 Version of Typescript: 5.5.3

Detailed Description

--

Breaking change?

--

github-actions[bot] commented 1 month ago

Hello there RomainGueffier 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

mattdean-digicatapult commented 1 month ago

The error

.tsoa/routes.ts:2638:56 - error TS2353: Object literal may only specify known properties, and '"multiple"' does not exist in type 'Field'.
  upload.fields([{"name":"file","maxCount":1,"multiple":false}]),

is something I came across and filed a bug for https://github.com/lukeautry/tsoa/issues/1642. Unfortunately it has been closed without a fix. I have recently done some more digging and think the issue is slightly more complicated than I originally thought. This stems from a change in https://github.com/lukeautry/tsoa/pull/1620 which introduced the property multiple onto a datatype being passed to multer. Unfortunately the type of the fields method doesn't expect this property. Originally I thought this was just something that can be removed but the property is being used in the hapi template https://github.com/lukeautry/tsoa/blob/d573d6fa4303b5c4236e06fac722bf3934b85359/packages/cli/src/routeGeneration/templates/hapi.hbs#L74.

I think there are two choices:

If one of the maintainers can comment I'm more than happy to contribute a fix to this part of the issue