ash-project / ash_json_api

The JSON:API extension for the Ash Framework
https://hexdocs.pm/ash_json_api
MIT License
55 stars 41 forks source link

OpenAPI spec compliance #189

Closed olivermt closed 1 month ago

olivermt commented 1 month ago

Hello, as described on discord, here is a list of all the compliance issues I have found so far:

Nullability

Current:

utm_zone:
                      anyOf:
                        - type: integer
                        - type: 'null' # Throws spec error

Required way to do it in openapi 3.0 ++

            utm_zone:
              type: integer
              nullable: true

Delete allows request body

/api/v4/cesium_assets/{id}/delete_staged_file:
    delete:
      callbacks: {}
      deprecated: false
      description: /cesium_assets/:id/delete_staged_file operation on cesium_asset resource
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/vnd.api+json:
            schema:
              additionalProperties: false
              properties:
                data:
                  additionalProperties: false
                  properties:
                    file_name:
                      type: string
                  required:
                    - file_name
                  type: object
              required:
                - data
              type: object
        description: Request body for the /cesium_assets/:id/delete_staged_file operation on cesium_asset resource
        required: true

Should just not emit body for DELETE I guess? This is a route to a generic action

Emitted regex for filters does not compile as regex

parameters:
        - description: Filters the query to results with attributes matching the given filter object
          in: query
          name: filter
          required: false
          schema:
            $ref: '#/components/schemas/cesium_asset-filter'
          style: deepObject
        - description: Sort order to apply to the results
          explode: false
          in: query
          name: sort
          required: false
          schema:
            pattern: ^(id|-id|++id|--id|cesium_asset_id|-cesium_asset_id|++cesium_asset_id|--cesium_asset_id|cesium_progress|-cesium_progress|++cesium_progress|--cesium_progress|tileset_url|-tileset_url|++tileset_url|--tileset_url|approved|-approved|++approved|--approved|error|-error|++error|--error|state|-state|++state|--state|cesium_upload_total|-cesium_upload_total|++cesium_upload_total|--cesium_upload_total|cesium_upload_todo|-cesium_upload_todo|++cesium_upload_todo|--cesium_upload_todo|cesium_download_total|-cesium_download_total|++cesium_download_total|--cesium_download_total|cesium_download_todo|-cesium_download_todo|++cesium_download_todo|--cesium_download_todo)(,(id|-id|++id|--id|cesium_asset_id|-cesium_asset_id|++cesium_asset_id|--cesium_asset_id|cesium_progress|-cesium_progress|++cesium_progress|--cesium_progress|tileset_url|-tileset_url|++tileset_url|--tileset_url|approved|-approved|++approved|--approved|error|-error|++error|--error|state|-state|++state|--state|cesium_upload_total|-cesium_upload_total|++cesium_upload_total|--cesium_upload_total|cesium_upload_todo|-cesium_upload_todo|++cesium_upload_todo|--cesium_upload_todo|cesium_download_total|-cesium_download_total|++cesium_download_total|--cesium_download_total|cesium_download_todo|-cesium_download_todo|++cesium_download_todo|--cesium_download_todo))*$
            type: string
          style: form
        - description: Paginates the response with the limit and offset or keyset pagination.
          in: query
          name: page
          required: true
          schema:
            properties:
              after:
                type: string
              before:
                type: string
              limit:
                minimum: 1
                type: integer
            type: object
          style: deepObject
        - description: Relationship paths to include in the response
          explode: false
          in: query
          name: include
          required: false
          schema:
            pattern: ^()(,())*$
            type: string
          style: form
        - description: Limits the response fields to only those listed for each type
          in: query
          name: fields
          required: false
          schema:
            additionalProperties: true
            properties:
              cesium_asset:
                description: Comma separated field names for cesium_asset
                example: id,cesium_asset_id,cesium_progress,utm_data,location,default_camera,tileset_url,approved,error,state
                type: string
            type: object
          style: deepObject

Bunch of errors like this:

image

Same with this smaller one with just a few filters:

pattern: ^(id|-id|++id|--id|name|-name|++name|--name)(,(id|-id|++id|--id|name|-name|++name|--name))*$

Primarily barfs at the usage of the ++ stuff it seems.

Some weirdness that passes the validator (overuse of anyOf?)

utm_hemisphere:
                              anyOf:
                                - enum:
                                    - north
                                    - south
                                  type: string
                                - enum:
                                    - north
                                    - south
                                  type: string

This is defined from this:

defmodule Safari.Virtual.CesiumAssetUtmHemisphereType do
  use Ash.Type.Enum, values: [north: "north", south: "south"]
end

The validator does not complain, but the TS generators are not quite sure what to make of this. This should probably not be an anyOf. In general it seems anyOf is used a lot of places where it should not in general.