yayoc / swagger-to-flowtype

Generate Flow types from swagger file

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Undesirable Flow type being generated from OpenAPI's `oneOf` keyword.

persianturtle opened this issue · comments

Consider the following OpenAPI schema:

{
    "openapi": "3.0.1",
    "paths": {
        "/v1/tool/breadcrumbs/{hierarchyId}/{categoryId}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get Breadcrumbs details",
                "operationId": "getBreadcrumbs",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "categoryId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Kitten"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/hierarchies": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get all available hierarchies ",
                "operationId": "getAllHierarchies",
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/HierarchyResponse"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/search/{hierarchyId}/{searchTerm}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Free text search categories for a given hierarchy",
                "operationId": "searchBy",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "searchTerm",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Kitten"
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        },
        "/v1/tool/category/{hierarchyId}/{categoryId}": {
            "get": {
                "tags": [
                    "V1-tool"
                ],
                "summary": "Get Category data needed to render a Table View in the Category Management tool",
                "operationId": "getTableView",
                "parameters": [
                    {
                        "name": "hierarchyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    },
                    {
                        "name": "categoryId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "minimum": 1,
                            "type": "integer",
                            "format": "int32"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "default response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TableViewResponse"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Auth": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "Kitten": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Kitten"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "HierarchyResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Hierarchy"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "AliasCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Alias"
                        ]
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "ChildCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Category"
                        ]
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "uri": {
                        "type": "string"
                    }
                }
            },
            "GblSubheaderResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Translation"
                        ]
                    },
                    "brandCatalogId": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "value": {
                        "type": "string"
                    }
                }
            },
            "Item": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string"
                    }
                },
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/ChildCategoryResponse"
                    },
                    {
                        "$ref": "#/components/schemas/AliasCategoryResponse"
                    },
                    {
                        "$ref": "#/components/schemas/SubheaderResponse"
                    }
                ]
            },
            "ParentCategoryResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "ParentCategory"
                        ]
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "SubheaderResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "Subheader"
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "translatedNames": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/GblSubheaderResponse"
                        }
                    }
                }
            },
            "TableViewResponse": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "DefaultCategory"
                        ]
                    },
                    "uri": {
                        "type": "string"
                    },
                    "level": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "integer",
                        "format": "int32"
                    },
                    "parentCategory": {
                        "$ref": "#/components/schemas/ParentCategoryResponse"
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Item"
                        }
                    }
                }
            }
        },
        "securitySchemes": {
            "Auth": {
                "type": "http",
                "description": "Token Authentication  e.g. Bearer <placeholder>",
                "scheme": "bearer",
                "bearerFormat": "JWT"
            }
        }
    }
}

The problem is that the Item type is defined as:

export type Item = { type: string };

And we'd like it to be defined instead as:

export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse

The relevant part of our OpenAPI schema is:

"Item": {
    "type": "object",
    "properties": {
        "type": {
            "type": "string"
        }
    },
    "oneOf": [
        {
            "$ref": "#/components/schemas/ChildCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/AliasCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/SubheaderResponse"
        }
    ]
},

I posted this Stack Overflow question and was informed that "oneOf and type are not supposed to be used together" and when replacing the above Item definition in OpenAPI schema with the following:

"Item": {
    "oneOf": [
        {
            "$ref": "#/components/schemas/ChildCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/AliasCategoryResponse"
        },
        {
            "$ref": "#/components/schemas/SubheaderResponse"
        }
    ],
    "discriminator": {
        "propertyName": "type",
        "mapping": {
            "Category": {
                "$ref": "#/components/schemas/ChildCategoryResponse"
            },
            "Alias": {
                "$ref": "#/components/schemas/AliasCategoryResponse"
            },
            "Subheader": {
                "$ref": "#/components/schemas/SubheaderResponse"
            }
        }
    }
},

swagger-typescript-api then outputs export type Item = ChildCategoryResponse | AliasCategoryResponse | SubheaderResponse; as Item's type definition while swagger-to-flowtype outputs export type Item = {};.

If we created a PR that solves this issue, would you be open to reviewing it?