cjbooms / fabrikt

Generates Kotlin Code from OpenApi3 Specifications
Apache License 2.0
156 stars 41 forks source link

Unresolved reference: Parameters on some APIs with params #236

Open thejeff77 opened 1 year ago

thejeff77 commented 1 year ago

When building certain spec files with parameters, building the final models results in the following.

> Task :fabrikt-client:compileKotlin FAILED
e: /Users/me@company.com/Projects/gha-kotlin-client-generate/fabrikt-client/src/main/kotlin/com/company/client/V1SomeresourceClient.kt: (5, 24): Unresolved reference: models
e: /Users/me@company.com/Projects/gha-kotlin-client-generate/fabrikt-client/src/main/kotlin/com/company/client/V1SomeresourceClient.kt: (36, 17): Unresolved reference: Parameters

Test file:

{
    "openapi": "3.0.1",
    "info": {
        "title": "Some Resource Service",
        "description": "Microservice for some resource",
        "version": "v0.0.1"
    },
    "servers": [
        {
            "url": "https://resource-service.com",
            "description": "Generated server url"
        }
    ],
    "paths": {
        "/v1/someresource": {
            "delete": {
                "operationId": "deleteSomeResource",
                "parameters": [
                    {
                        "name": "account-id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "role",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "requester-id",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "statusCode",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "BROKEN",
                                "WORKING",
                                "MESSED-UP"
                            ]
                        }
                    }
                ],
            }
        }
    },
    "components": {
        "schemas": {
        }
    }
}

Generated File that won't build V1SomeresourceClient.kt:

package com.company.client

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import com.company.models.Parameters
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.Map
import kotlin.jvm.Throws
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request

@Suppress("unused")
class V1SomeresourceClient(
  private val objectMapper: ObjectMapper,
  private val baseUrl: String,
  private val client: OkHttpClient
) {
  /**
   *
   *
   * @param accountId 
   * @param role 
   * @param requesterId 
   * @param statusCode 
   */
  @Throws(ApiException::class)
  fun deleteSomeResource(
    accountId: String,
    role: String,
    requesterId: String,
    statusCode: Parameters? = null,
    additionalHeaders: Map<String, String> = emptyMap()
  ): ApiResponse<Unit> {
    val httpUrl: HttpUrl = "$baseUrl/v1/someresource"
    .pathParam("{account-id}" to accountId)
    .toHttpUrl()
    .newBuilder()
    .queryParam("statusCode", statusCode)
    .build()

    val headerBuilder = Headers.Builder()
    .header("role", role)
    .header("requester-id", requesterId)
    additionalHeaders.forEach { headerBuilder.header(it.key, it.value) }
    val httpHeaders: Headers = headerBuilder.build()

    val request: Request = Request.Builder()
    .url(httpUrl)
    .headers(httpHeaders)
    .delete()
    .build()

    return request.execute(client, objectMapper, jacksonTypeRef())
  }
}
cjbooms commented 1 year ago

Try moving your inline schema definitions into proper schema definitions

thejeff77 commented 1 year ago

@cjbooms thanks for the suggestion!

I checked the validity of my example, and it seems it has issues, like it needs a response block defined.

I believe inline model definitions are valid though. This is something I pulled from Spring's spring doc oapi spec pulled from several services. If an enum is not reused, springdoc will opt to define it inline.

Copying these and mutating them to fix generator issues is less than desired for valid spec files.

cjbooms commented 1 year ago

Inline schemas are valid but support in fabrikt isn't present in all circumstances. https://github.com/cjbooms/fabrikt/issues/187

Generally it's just easier to define a schema for these in the schema section as that provides fabrikt with a unique class name it can use

thejeff77 commented 1 year ago

Ok thanks for the workaround, we've converted to string types where we need to use this generator. Will leave this open as a feature request.