lukeautry / tsoa

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

Add ability for custom annotations to write Extensions #1532

Open gwprice115 opened 7 months ago

gwprice115 commented 7 months ago

Sorting

Expected Behavior

        "x-rate-limit-docs": [
          {
            "rate": "15",
            "period": "second"
          }
        ]

I expected that I could have my custom annotation write extensions to swagger.json by calling Extension inside it, but that turned out not to be the case. I dug in and came up with this proposal:

I want to be able to configure extensions for custom middleware, e.g.

const specAndRouteArgs: SwaggerArgs = {
  json: true,
  configuration: {
    spec: specConfig,
    routes: routesConfig,
    entryFile: "src/index.ts",
    customSwaggerExtensions: [
      {
        decoratorName: "RateLimit",
        name: "x-rate-limit-docs",
        value: (args) => {
          return [{ rate: args[0].getText(), period: args[1].getText() }];
        }
      },
    ],
  },
};

This would also create a work-around for https://github.com/lukeautry/tsoa/issues/771 https://github.com/lukeautry/tsoa/issues/1213 https://github.com/lukeautry/tsoa/issues/1520 etc. because you could write a function to dynamically resolve extensions

Current Behavior

Currently there is no way to add extensions in swagger to all endpoints that have a certain decorator (in my case a custom @RateLimit decorator that wraps Middlewares)

Possible Solution

I think the best way to solve this problem is to add an optional customSwaggerExtension object to the config

Steps to Reproduce

N/A

Context (Environment)

Version of the library: Version of NodeJS:

Detailed Description

For my service, I wrote a custom annotation called @RateLimit that uses Middlewares under the hood to rate limit API calls based on the passed in rate and key. I want these rate limits to also be reflected in the documentation, which requires adding an extension to the swagger.json exactly like the @Extension annotation does today. I don't want to have to annotate each of my API calls twice, once for the actual rate limit and once to document it.

In my proposal, users can optionally add a customSwaggerExtensions field to the tsoa configuration which will create an extension to go with a given annotation. The typescript is:

customSwaggerExtensions?: Array<
    {
      decoratorName: string,
      name: `x-${string}`,
      value: (args: ts.NodeArray<ts.Expression>) => Array<ExtensionType | ExtensionType[]>,
    }>

I am submitting a proof-of-concept PR in conjunction with the issue--would love any and all feedback, and am happy to work to make it meet the contribution standards once I know that you all are aligned with the philosophy

Breaking change?

No

github-actions[bot] commented 7 months ago

Hello there gwprice115 👋

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

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