aj-foster / open-api-generator

Open API code generator for Elixir
MIT License
97 stars 13 forks source link

Function Clause Error when operationId is not specified. #30

Closed mpope9 closed 9 months ago

mpope9 commented 10 months ago

Hello, trying out this library and it is very cool thank you for your work.

One thing that tripped me up was that the following function clause error is thrown if the operationId isn't present in a path def:

** (FunctionClauseError) no function clause matching in String.split/3

    The following arguments were given to String.split/3:

        # 1
        nil

        # 2
        "/"

        # 3
        [trim: true]

    Attempted function clauses (showing 3 out of 3):

        def split(string, %Regex{} = pattern, options) when is_binary(string) and is_list(options)
        def split(string, "", options) when is_binary(string) and is_list(options)
        def split(string, pattern, options) when is_binary(string) and is_list(options)

    (elixir 1.13.4) lib/string.ex:473: String.split/3
    (oapi_generator 0.1.0-rc.3) lib/open_api/processor/naming.ex:108: OpenAPI.Processor.Naming.operation_modules/2
    (oapi_generator 0.1.0-rc.3) lib/open_api/processor.ex:279: OpenAPI.Processor.process_operation/2
    (elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
    (stdlib 4.3.1.2) maps.erl:411: :maps.fold_1/3
    (oapi_generator 0.1.0-rc.3) lib/open_api/processor.ex:42: OpenAPI.Processor.run/1
    (oapi_generator 0.1.0-rc.3) lib/open_api.ex:50: OpenAPI.run/2
    (mix 1.13.4) lib/mix/task.ex:397: anonymous fn/3 in Mix.Task.run_task/3

Very minor issue.

aj-foster commented 10 months ago

Hello there! 👋🏼

Thanks for letting me know. I didn't anticipate operations without an operationId, but I suppose the spec leaves open the possibility:

operationId: Unique string used to identify the operation. The id MUST be unique among all operations described in the API. The operationId value is case-sensitive. Tools and libraries MAY use the operationId to uniquely identify an operation, therefore, it is RECOMMENDED to follow common programming naming conventions.

If you have a chance, could you share the OpenAPI description that created this error? We'll need to figure out a backup way of determining the name of the operation using other pieces of available data.

mpope9 commented 10 months ago

I distilled this one from the swagger editor's default example:

openapi: 3.0.3
info:
  title: Swagger Petstore - OpenAPI 3.0
  description: |-
    Pet shop description
  termsOfService: http://swagger.io/terms/
  contact:
    email: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.11
servers:
  - url: https://petstore3.swagger.io/api/v3
tags:
  - name: pet
    description: Everything about your Pets
    externalDocs:
      description: Find out more
      url: http://swagger.io
paths:
  /pet:
    put:
      tags:
        - pet
      summary: Update an existing pet
      description: Update an existing pet by Id
      #operationId: updatePet
      requestBody:
        description: Update an existent pet in the store
        content:
          application/json:
            schema:
              type: object
              properties:
                myProp:
                  type: string
                  example: asdf
        required: true
      responses:
        '200':
          description: Successful operation

Seems to render fine there.

mpope9 commented 9 months ago

Unrelated to this issue, I was evaluating the OpenAPI cli generators for both Elixir and Erlang, and nether produced compile-able results for a rather simple api def. This library did. Well done on this.

aj-foster commented 9 months ago

Hi there! Sorry for the delay; I just push a commit to handle nil operation IDs. For now, it will fall back to tags and path/method information for a default name. Definitely open to better solutions here, but this should unblock you for now.

Glad to hear it's working for you! An Elixir-native solution seemed like the best way to get high-quality Elixir code, and so far it seems to be going well.