ts-spec / tspec

Type-driven API Documentation library. Auto-generating REST API document based on TypeScript types.
https://ts-spec.github.io/tspec/
MIT License
107 stars 5 forks source link

Question: how to support multiple content-types for the same response? #39

Open lah-wag opened 10 months ago

lah-wag commented 10 months ago

Hey,

Is it possible to describe a response with multiple content-types using tspec? Example from: https://swagger.io/docs/specification/describing-responses/

paths:
  /users:
    get:
      summary: Get all users
      responses:
        '200':
          description: A list of users
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArrayOfUsers'
            application/xml:
              schema:
                $ref: '#/components/schemas/ArrayOfUsers'
            text/plain:
              schema:
                type: string

It seems that I would add the mediatype as js-doc to the reponse like in this example: https://ts-spec.github.io/tspec/guide/file-upload-download#file-download

export type UserApiSpec = Tspec.DefineApiSpec<{
  tags: ["Users"];
  paths: {
    "/api/users": {
      get: {
        summary: "Get all users";
        responses: {
          /** @mediaType application/json */
          /** @mediaType text/xml */
          200: Users[];
        };
      };
    };
  };
}>;

But that just takes the last value:

  "/api/users": {
      "get": {
        "operationId": "UserApiSpec_get_/api/users",
        "tags": [
          "Users"
        ],
        "summary": "Get all users",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "text/xml": {
                "schema": {
                  "mediaType": "text/xml",
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Users"
                  }
                }
              }
            }
          }
        }
      }
    }
hyeonss0417 commented 9 months ago

We don't support multiple content-types yet, but we'll work on it in the near future.

I'm thinking of working with the following format, what do you think?

export type UserApiSpec = Tspec.DefineApiSpec<{
  tags: ["Users"];
  paths: {
    "/api/users": {
      get: {
        summary: "Get all users";
        responses: {
          /** @mediaType ["application/json", "text/xml"] */
          200: Users[];
        };
      };
    };
  };
}>;
lah-wag commented 9 months ago

We don't support multiple content-types yet, but we'll work on it in the near future.

I'm thinking of working with the following format, what do you think?

export type UserApiSpec = Tspec.DefineApiSpec<{
  tags: ["Users"];
  paths: {
    "/api/users": {
      get: {
        summary: "Get all users";
        responses: {
          /** @mediaType ["application/json", "text/xml"] */
          200: Users[];
        };
      };
    };
  };
}>;

Glad that you find it useful and will consider adding the feature. To align with OpenAPI I think that individual mediatypes should have their own response object. Something like this:

export type UserApiSpec = Tspec.DefineApiSpec<{
  tags: ["Users"];
  paths: {
    "/api/users": {
      get: {
        summary: "Get all users";
        responses: {
             200: {
               "application/json": Users[],
               "application/xml": UsersXML[],
               "text/plain": string,
             }
        };
      };
    };
  };
}>;

Obviously this example should be reworked to use annotations instead.

yeonjoon-ridi commented 2 weeks ago

any updates on this? @hyeonss0417 we'd appreciate update on multipart/form-data

hyeonss0417 commented 1 week ago

@yeonjoon-ridi If you only want to use multipart/form-data, you can follow the instructions below, as described in the Tspec official documentation.

export type FileApiSpec = Tspec.DefineApiSpec<{
  paths: {
    '/files/upload': {
      post: {
        summary: 'Upload File',
        /** @mediaType multipart/form-data */
        body: {
          file: Tspec.BinaryString;
        },
        responses: { 200: { fileName: string } },
      },
    },
  },
}>;

https://ts-spec.github.io/tspec/guide/file-upload-download

Or do you want to create schemas with multiple response formats within the same status code, as discussed above?