orval icon indicating copy to clipboard operation
orval copied to clipboard

OpenAPI spec parsing bug

Open sengeezer opened this issue 1 year ago • 11 comments

What are the steps to reproduce this issue?

  1. Run Orval using an OpenAPI spec containing the following (sanitised) section. Only provide the input and output parameters on CLI.
{
  "openapi": "3.0.1",
  "info": {
    "title": "API",
    "description": "An API",
    "termsOfService": "https://example.com",
    "license": {
      "name": "company",
      "url": "https://www.example.com"
    },
    "version": "1.0.0"
  },
  "servers": [
  {
    "url": "https://dev.dev",
    "description": "Generated server url"
  }
],
  "paths": {
    "/api/v1/path/{additional}" : {
      "get": {
        "tags": [],
        "summary": "Fetches",
        "operationId": "getHierarchy_1",
        "parameters": [
          {
            "name": "hierarchy",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "requestParameters",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/HierarchyRequestParams"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/path1/{otherAdditional}" : {
      "get": {
        "tags": [],
        "summary": "Fetches",
        "operationId": "getHierarchy_2",
        "parameters": [
          {
            "name": "requestParameters",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/HierarchyRequestParams"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          }
        },
        "deprecated": true
      }
    }
  }
}

What happens?

Orval fails to complete the generation process.

What were you expecting to happen?

Orval should have completed the generation process successfully.

Any logs, error output, etc?

api - Error: The path params level can't be found in parameters (getHierarchy_2)
    at /users/dev/app/node_modules/@orval/core/dist/index.js:49180:13
    at Array.map (<anonymous>)
    at getParams (/users/dev/app/node_modules/@orval/core/dist/index.js:49171:17)
    at generateVerbOptions (/users/dev/app/node_modules/@orval/core/dist/index.js:50418:18)
    at /users/dev/app/node_modules/@orval/core/dist/index.js:50502:33
    at asyncReduce (/users/dev/app/node_modules/@orval/core/dist/index.js:47318:24)
    at generateVerbsOptions (/users/dev/app/node_modules/@orval/core/dist/index.js:50498:7)
    at api.operations (/users/dev/app/node_modules/orval/dist/bin/orval.js:3429:70)
    at asyncReduce (/users/dev/app/node_modules/@orval/core/dist/index.js:47318:24)
    at async getApiBuilder (/users/dev/app/node_modules/orval/dist/bin/orval.js:3413:15)

Any other comments?

I had a conversation about this on the Orval DIscord on August 23 2024 (username: helveticDev).

The OpenAPI spec validates and works without issues with npx openapi-typescript.

What versions are you using?

  System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M2
    Memory: 44.64 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  npmPackages:
    msw: ^2.3.1 => 2.3.1
    orval: ^7.0.1 => 7.0.1
    react: ^18.3.1 => 18.3.1

sengeezer avatar Aug 28 '24 11:08 sengeezer

@sengeezer i see its referencing params like "$ref": "#/components/schemas/HierarchyRequestParams" but I don't see those in your Schema. Could that be the issue its trying to reference something that doesn't exist?

melloware avatar Aug 28 '24 12:08 melloware

Also I see this /api/v1/path1/{otherAdditional} so its expecting a path param called OtherAdditional but i don't see that listed in your OpenAPI either.

melloware avatar Aug 28 '24 12:08 melloware

For example here is one of mine.

 "/administrator/queue/{id}" : {
      "get" : {
        "tags" : [ "Mobile Synchronization Administrator Resource" ],
        "parameters" : [ {
          "name" : "id",
          "in" : "path",
          "required" : true,
          "schema" : {
            "format" : "int64",
            "minimum" : 0,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "OK",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/IosNotificationQueue"
                }
              }
            }
          }
        }
      }
    },

see how the path param id has a matching declaration.

melloware avatar Aug 28 '24 12:08 melloware

Ok, I can see I've sanitised the spec into invqalidity. I have asked for permission to share more.

sengeezer avatar Aug 28 '24 13:08 sengeezer

I also just verified that your competitor (?) openapi-ts also has no issues parsing the same OpenAPI spec. Hopefully I will recieve approval so Orval is not the only one to barf on the spec. :)

sengeezer avatar Aug 28 '24 13:08 sengeezer

looks like openapi-ts doesn't do TanStack Query? only native Fetch?

melloware avatar Aug 28 '24 13:08 melloware

Ok, my infosec analyst has approved the following. Will this help?

{
  "openapi": "3.0.1",
  "info": {
    "title": "API",
    "description": "An API",
    "termsOfService": "https://example.com",
    "license": {
      "name": "company",
      "url": "https://www.example.com"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://dev.dev",
      "description": "Generated server url"
    }
  ],
  "paths": {
    "/api/v1/path/{hierarchy}": {
      "get": {
        "tags": [],
        "summary": "Fetches",
        "operationId": "getHierarchy_1",
        "parameters": [
          {
            "name": "hierarchy",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "requestParameters",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/HierarchyRequestParams"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/path1/{level}": {
      "get": {
        "tags": [],
        "summary": "Fetches",
        "operationId": "getHierarchy_2",
        "parameters": [
          {
            "name": "requestParameters",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/HierarchyRequestParams"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWrapperHierarchyBean"
                }
              }
            }
          }
        },
        "deprecated": true
      }
    }
  },
  "components": {
    "schemas": {
      "HierarchyRequestParams": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "search": {
            "type": "string"
          },
          "searchType": {
            "type": "string",
            "enum": [
              "INCREMENTAL",
              "COMPLETE",
              "ALL_LEVELS",
              "ALL_SKUS"
            ]
          },
          "licenced": {
            "type": "boolean"
          },
          "value": {
            "type": "integer",
            "format": "int64"
          },
          "level": {
            "type": "string"
          },
          "useFilter": {
            "type": "boolean"
          },
          "sortBy": {
            "type": "string"
          },
          "tradingHierarchy": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "brand": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ownBrand": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "manufacturer": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "packSize": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "unitOfMeasure": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "measures": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "resolve": {
            "type": "string",
            "enum": [
              "category",
              "product",
              "brand",
              "own_brand",
              "all"
            ]
          },
          "ownBrandOnly": {
            "type": "boolean"
          },
          "liveSkusOnly": {
            "type": "boolean"
          },
          "minMeasure": {
            "type": "integer",
            "format": "int32"
          },
          "maxMeasure": {
            "type": "integer",
            "format": "int32"
          },
          "atomicMeasures": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "brandIds": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            }
          },
          "ownBrandLabels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "splitSearchTerms": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ResponseWrapperHierarchyBean": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "100 CONTINUE",
              "101 SWITCHING_PROTOCOLS",
              "102 PROCESSING",
              "103 EARLY_HINTS",
              "103 CHECKPOINT",
              "200 OK",
              "201 CREATED",
              "202 ACCEPTED",
              "203 NON_AUTHORITATIVE_INFORMATION",
              "204 NO_CONTENT",
              "205 RESET_CONTENT",
              "206 PARTIAL_CONTENT",
              "207 MULTI_STATUS",
              "208 ALREADY_REPORTED",
              "226 IM_USED",
              "300 MULTIPLE_CHOICES",
              "301 MOVED_PERMANENTLY",
              "302 FOUND",
              "302 MOVED_TEMPORARILY",
              "303 SEE_OTHER",
              "304 NOT_MODIFIED",
              "305 USE_PROXY",
              "307 TEMPORARY_REDIRECT",
              "308 PERMANENT_REDIRECT",
              "400 BAD_REQUEST",
              "401 UNAUTHORIZED",
              "402 PAYMENT_REQUIRED",
              "403 FORBIDDEN",
              "404 NOT_FOUND",
              "405 METHOD_NOT_ALLOWED",
              "406 NOT_ACCEPTABLE",
              "407 PROXY_AUTHENTICATION_REQUIRED",
              "408 REQUEST_TIMEOUT",
              "409 CONFLICT",
              "410 GONE",
              "411 LENGTH_REQUIRED",
              "412 PRECONDITION_FAILED",
              "413 PAYLOAD_TOO_LARGE",
              "413 REQUEST_ENTITY_TOO_LARGE",
              "414 URI_TOO_LONG",
              "414 REQUEST_URI_TOO_LONG",
              "415 UNSUPPORTED_MEDIA_TYPE",
              "416 REQUESTED_RANGE_NOT_SATISFIABLE",
              "417 EXPECTATION_FAILED",
              "418 I_AM_A_TEAPOT",
              "419 INSUFFICIENT_SPACE_ON_RESOURCE",
              "420 METHOD_FAILURE",
              "421 DESTINATION_LOCKED",
              "422 UNPROCESSABLE_ENTITY",
              "423 LOCKED",
              "424 FAILED_DEPENDENCY",
              "425 TOO_EARLY",
              "426 UPGRADE_REQUIRED",
              "428 PRECONDITION_REQUIRED",
              "429 TOO_MANY_REQUESTS",
              "431 REQUEST_HEADER_FIELDS_TOO_LARGE",
              "451 UNAVAILABLE_FOR_LEGAL_REASONS",
              "500 INTERNAL_SERVER_ERROR",
              "501 NOT_IMPLEMENTED",
              "502 BAD_GATEWAY",
              "503 SERVICE_UNAVAILABLE",
              "504 GATEWAY_TIMEOUT",
              "505 HTTP_VERSION_NOT_SUPPORTED",
              "506 VARIANT_ALSO_NEGOTIATES",
              "507 INSUFFICIENT_STORAGE",
              "508 LOOP_DETECTED",
              "509 BANDWIDTH_LIMIT_EXCEEDED",
              "510 NOT_EXTENDED",
              "511 NETWORK_AUTHENTICATION_REQUIRED"
            ]
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationErrorMappingBean"
            }
          },
          "body": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductHierarchyBean"
            }
          }
        }
      },
      "ValidationErrorMappingBean": {
        "type": "object",
        "properties": {
          "fieldMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "writeOnly": true
          }
        }
      },
      "ProductHierarchyBean": {
        "type": "object",
        "properties": {
          "value": {
            "type": "integer",
            "format": "int64"
          },
          "label": {
            "type": "string"
          },
          "level": {
            "type": "string"
          },
          "accesslevels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccessLevelsBean"
            }
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductHierarchyBean"
            }
          },
          "skuCount": {
            "type": "integer",
            "format": "int32"
          },
          "isFinal": {
            "type": "boolean"
          },
          "isProductLevel": {
            "type": "boolean"
          },
          "fullAccess": {
            "type": "boolean"
          },
          "parent": {
            "$ref": "#/components/schemas/ProductHierarchyBean"
          },
          "groupLabel": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "searchIndex": {
            "type": "string"
          },
          "parents": {
            "type": "string"
          }
        }
      },
      "AccessLevelsBean": {
        "type": "object",
        "properties": {
          "epos": {
            "type": "string"
          },
          "access": {
            "type": "string"
          }
        }
      }
    }
  }
}

sengeezer avatar Aug 28 '24 15:08 sengeezer

if you run the above through the CLI does it error the same way?

melloware avatar Aug 28 '24 15:08 melloware

It does, yes.

The new stack trace:

api - Error: The path params level can't be found in parameters (getHierarchy_2)
    at /users/dev/app/node_modules/@orval/core/dist/index.js:49180:13
    at Array.map (<anonymous>)
    at getParams (/users/dev/app/node_modules/@orval/core/dist/index.js:49171:17)
    at generateVerbOptions (/users/dev/app/node_modules/@orval/core/dist/index.js:50418:18)
    at /users/dev/app/node_modules/@orval/core/dist/index.js:50502:33
    at asyncReduce (/users/dev/app/node_modules/@orval/core/dist/index.js:47318:24)
    at generateVerbsOptions (/users/dev/app/node_modules/@orval/core/dist/index.js:50498:7)
    at api.operations (/users/dev/app/node_modules/orval/dist/bin/orval.js:3429:70)
    at asyncReduce (/users/dev/app/node_modules/@orval/core/dist/index.js:47318:24)
    at async getApiBuilder (/users/dev/app/node_modules/orval/dist/bin/orval.js:3413:15)

sengeezer avatar Aug 28 '24 15:08 sengeezer

@anymaniax / @melloware : Are there any updates on this? Could you give me an ETA for this to be fixed?

I can confirm that v7.1.0 does NOT fix this bug.

sengeezer avatar Sep 04 '24 12:09 sengeezer

No ETA from my end i would expect someone in the community needs to submit a PR to fix this issue.

melloware avatar Sep 04 '24 13:09 melloware

This crash because the path /api/v1/path1/{level} has a param level and it's not described in the parameters array. It's the good behavior or I miss something?

anymaniax avatar Nov 30 '24 07:11 anymaniax