typescript icon indicating copy to clipboard operation
typescript copied to clipboard

CORS config TS types (both here and in @types) don't match the schema

Open justingrant opened this issue 3 years ago • 5 comments

I ran into https://github.com/serverless/serverless/issues/9858 because the TS types don't have an accurate type for HttpCors.

Here's the schema: https://github.com/serverless/serverless/blob/ef5a8faf13a8fbf8564e7c0621e88d1ea5357ea5/lib/plugins/aws/package/compile/events/apiGateway/index.js#L77-L98

The current type in this repo is essentially a no-op. https://github.com/serverless/typescript/blob/b700b729a0ad15aac0a6ed9dc146047a2a7aa583/index.d.ts#L190-L199

The current type in @types/serverless is incomplete (missing origin and methods properties) and inaccurate (one of origin or origins is required, not optional, making it easy to run into https://github.com/serverless/serverless/issues/9858). Also, all the optional properties have | undefined appended which AFAIK is redundant and unnecessary.

The actual types should be something like this:

type HttpCors = 
(
  | { origins: string | string[]; origin?: undefined }
  | { origin: string; origins?: undefined }
) & {
  headers?: string | string[];
  allowCredentials?: boolean;
  maxAge?: number;
  cacheControl?: string;
  methods?: string[];
};

or this

interface HttpCorsBase {
  headers?: string | string[];
  allowCredentials?: boolean;
  maxAge?: number;
  cacheControl?: string;
  methods?: string[];
};
interface HttpCorsOrigin extends HttpCorsBase {
  origin: string;
  origins?: undefined;
}
interface HttpCorsOrigins extends HttpCorsBase {
  origins: string | string[];
  origin?: undefined;
}
interface Http {
  path: string;
  method: string;
  cors?: boolean | HttpCorsOrigin | HttpCorsOrigins | undefined;
  ...

justingrant avatar Aug 19 '21 19:08 justingrant

Thanks for pointing out this issue @justingrant . Types from this repository are auto-generated from schema located in https://github.com/serverless/serverless. The library handling the type generation is struggling with the oneOf keyword located in the required section of the CORS schema. Once it is removed, chances are next type generation will be much more accurate.

I tried removing this oneOf property to give it a try and actually got correctly generated types image

fredericbarthelet avatar Aug 20 '21 07:08 fredericbarthelet

I tried removing this oneOf property to give it a try and actually got correctly generated types

Those types don't actually look correct:

  • One of origin or origins is required or validation will fail (serverless/serverless#9858)
  • If I remember correctly, headers (and maybe methods too?) accepts a comma-delimited string as well as a string[]
  • integration?: string | string | string | string ... is that missing the string enum values?

justingrant avatar Aug 20 '21 19:08 justingrant

I've also just come across this. In my case, I'm interested in the exposedResponseHeaders property that is available in the YAML configuration but not in the TypeScript equivalent:

provider:
  httpApi:
    cors:
      allowedOrigins:
        - https://url1.com
        - https://url2.com
      allowedHeaders:
        - Content-Type
        - Authorization
      allowedMethods:
        - GET
      allowCredentials: true
      exposedResponseHeaders:
        - Special-Response-Header
      maxAge: 6000 # In seconds

(from https://www.serverless.com/blog/aws-http-api-support#configuring-cors).

I notice that exposedResponseHeaders is not listed as a valid property in the CORS schema. Is there a reason for that?

ed-graham avatar Oct 18 '21 14:10 ed-graham

Hi @ed-graham, the exposedResponseHeaders property is available in the typescript definition from this repository in https://github.com/serverless/typescript/blob/bc84be8ef13ab8cf5292c82b4d27303adceda58b/index.d.ts#L821

The documentation you're referring to is for httpApi event types, that are provisioned with API Gateway HTTP API. However the code base containing CORS schema you're referring to is for http event types, that are provisioned with API Gateway Rest API. Those are not the same and does not share the same capabilities.

fredericbarthelet avatar Oct 18 '21 16:10 fredericbarthelet

Thanks @fredericbarthelet - that's really helpful! I didn't realise I had the two things mixed up. It turns out that I was still using the old community-maintained Definitely Typed package rather than your new one: so now I've upgraded and everything is working as expected.

ed-graham avatar Oct 19 '21 11:10 ed-graham