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?