orval icon indicating copy to clipboard operation
orval copied to clipboard

OpenAPI: Support for `const` values in string parameter types

Open appleton opened this issue 10 months ago • 5 comments

What are the steps to reproduce this issue?

Given a schema like this:

     responses:
        "200":
          content:
            text/event-stream:
              schema:
                description: Each oneOf object in the array represents one possible Server Sent Events (SSE) message, serialized as UTF-8 text according to the SSE specification.
                items:
                  oneOf:
                    - properties:
                        data:
                          $ref: "#/components/schemas/ResponseError"
                        event:
                          const: error
                          description: The event name.
                          type: string
                        id:
                          description: The event ID.
                          type: integer
                        retry:
                          description: The retry time in milliseconds.
                          type: integer
                      required:
                        - data
                        - event
                      title: Event error
                      type: object
                    - properties:
                        data:
                          $ref: "#/components/schemas/ResponseData"
                        event:
                          const: data
                          description: The event name.
                          type: string
                        id:
                          description: The event ID.
                          type: integer
                        retry:
                          description: The retry time in milliseconds.
                          type: integer
                      required:
                        - data
                        - event
                      title: Event data
                      type: object

What happens?

My schema types actually look like this:

export type Response200ItemOneOf = {
  data: ResponseError;
  /** The event name. */
  event: string;
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

export type Response200ItemOneOfTwo = {
  data: ResponseData;
  /** The event name. */
  event: string;
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

What were you expecting to happen?

For my schema types to look like this. Note that the event property is restricted to only the const value (error or data).

export type Response200ItemOneOf = {
  data: ResponseError;
  /** The event name. */
  event: "error";
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

export type Response200ItemOneOfTwo = {
  data: ResponseData;
  /** The event name. */
  event: "data";
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

Any other comments?

I guess that either const isn't supported or maybe I'm just doing something wrong?

What versions are you using?

Operating System: MacOS 14.4.1 Package Version: 6.27.1 Browser Version: N/A

appleton avatar Apr 23 '24 13:04 appleton

But isn't that what const means? What were you expecting in the output?

melloware avatar Apr 23 '24 13:04 melloware

Specifically I'm expecting my event fields to look like this:

  event: "data";
// and
  event: "error";

but they actually look like this:

  event: string;
// and
  event: string;

appleton avatar Apr 23 '24 13:04 appleton

@appleton I think you should define event as enum to get expected result

https://swagger.io/docs/specification/data-models/enums/

      responses:
        "200":
          content:
            text/event-stream:
              schema:
                description: Each oneOf object in the array represents one possible Server Sent Events (SSE) message, serialized as UTF-8 text according to the SSE specification.
                items:
                  oneOf:
                    - properties:
                        data:
                          $ref: "#/components/schemas/ResponseError"
                        event:
                          enum:
                            - error
                            - data
                          description: The event name.
                          type: string
                          default: 'error'
                        id:
                          description: The event ID.
                          type: integer
                        retry:
                          description: The retry time in milliseconds.
                          type: integer
                      required:
                        - data
                        - event
                      title: Event error
                      type: object
                    - properties:
                        data:
                          $ref: "#/components/schemas/ResponseData"
                        event:
                          enum:
                            - error
                            - data
                          description: The event name.
                          type: string
                          default: 'data'
                        id:
                          description: The event ID.
                          type: integer
                        retry:
                          description: The retry time in milliseconds.
                          type: integer
                      required:
                        - data
                        - event
                      title: Event data
                      type: object

mortezakarimi avatar Apr 25 '24 07:04 mortezakarimi

Hi @mortezakarimi thanks for the suggestion. It's better but it doesn't quite give me the result I'm after:

export const PromptModel200ItemOneOfThreeEvent = {
  error: 'error',
  data: 'data',
} as const;

export type Response200ItemOneOf = {
  data: ResponseError;
  /** The event name. */
  event: PromptModel200ItemOneOfThreeEvent;
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

export type Response200ItemOneOfTwo = {
  data: ResponseData;
  /** The event name. */
  event: PromptModel200ItemOneOfThreeEvent;
  /** The event ID. */
  id?: number;
  /** The retry time in milliseconds. */
  retry?: number;
};

What I want to be able to do in my application code is have a succinct way to type switch on the objects and one way to do that (if I had the output I was expecting from the const declaration) would be:

// response is a Response200ItemOneOf | Response200ItemOneOfTwo
switch(response.event) {
  case "error":
    // response is now a Response200ItemOneOf
  break;
  case "data":
    // response is now a Response200ItemOneOfTwo
  break;
}

appleton avatar Apr 25 '24 08:04 appleton

I ran into this as well and tried to fix it in #1376 but it seems that the const keyword is supported, as long as you don't combine it with a type. Having a property defined as:

constant:
  type: string
  const: something

is generated as

constant: string;

while a property defined as:

constant:
  const: something

is generated as

constant: "something";

I'm not sure if this is a valid specification, it might be that type should always be specified, but it does solve the problem for me.

RinseV avatar May 15 '24 13:05 RinseV