Merge pull request #1 from lg-backbone/feature/petstoreParity

This commit is contained in:
Ryan Brink
2021-04-11 15:07:45 -04:00
committed by GitHub
20 changed files with 298 additions and 61 deletions

37
.github/workflows/pr_checks.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Run PR Checks
on: pull_request
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.14
uses: actions/setup-java@v1
with:
java-version: 1.14
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle
- name: Lint using detekt
run: ./gradlew detekt
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.14
uses: actions/setup-java@v1
with:
java-version: 1.14
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle
- name: Assemble with Gradle
run: ./gradlew assemble
- name: Run Unit Tests
run: ./gradlew test

22
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Publish to GitHub Packages
on:
push:
branches: [ main ]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.14
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle
- name: Publish package
run: ./gradlew publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
# Ignore Gradle build output directory
build
.idea

View File

@ -16,6 +16,7 @@ allprojects {
repositories {
mavenCentral()
maven { url = uri("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") }
}
apply(plugin = "org.jetbrains.kotlin.jvm")

View File

@ -361,7 +361,7 @@ naming:
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
classPattern: '[A-Z][a-zA-Z0-9]*'
ConstructorParameterNaming:
active: true
active: false
excludes: ['**/test/**', '**/testIntegration/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'

View File

@ -10,3 +10,21 @@ dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0")
}
publishing {
repositories {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/lg-backbone/kompendium")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("kompendium") {
from(components["kotlin"])
}
}
}

View File

@ -1,10 +0,0 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package kompendium
class Library {
fun someLibraryMethod(): String {
return "Heya"
}
}

View File

@ -1,6 +1,5 @@
package org.leafygreens.kompendium
import java.net.URI
import org.leafygreens.kompendium.models.OpenApiSpec
class Kompendium {

View File

@ -3,10 +3,12 @@ package org.leafygreens.kompendium.models
data class OpenApiSpec(
val openapi: String = "3.0.3",
val info: OpenApiSpecInfo? = null,
val servers: List<OpenApiSpecServer> = emptyList(), // TODO Needs to default to server object with url of `/`
val paths: Map<String, OpenApiSpecPathItem> = emptyMap(),
// TODO Needs to default to server object with url of `/`
val servers: List<OpenApiSpecServer>? = null,
val paths: Map<String, OpenApiSpecPathItem>? = null,
val components: OpenApiSpecComponents? = null,
val security: Map<String, String> = emptyMap(), // todo needs to reference objects in the components -> security scheme 🤔
val tags: List<OpenApiSpecTag> = emptyList(),
// todo needs to reference objects in the components -> security scheme 🤔
val security: List<Map<String, List<String>>>? = null,
val tags: List<OpenApiSpecTag>? = null,
val externalDocs: OpenApiSpecExternalDocumentation? = null
)

View File

@ -2,5 +2,5 @@ package org.leafygreens.kompendium.models
// TODO I *think* the only thing I need here is the security https://swagger.io/specification/#components-object
data class OpenApiSpecComponents(
val securitySchemes: Map<String, OpenApiSpecReferencable>
val securitySchemes: Map<String, OpenApiSpecSchema>
)

View File

@ -2,7 +2,7 @@ package org.leafygreens.kompendium.models
// TODO Oof -> https://swagger.io/specification/#media-type-object
data class OpenApiSpecMediaType(
val schema: OpenApiSpecReferencable, // TODO sheesh -> https://swagger.io/specification/#schema-object needs to be referencable
val schema: OpenApiSpecSchema, // TODO sheesh -> https://swagger.io/specification/#schema-object
val example: String? = null, // TODO Enforce type? then serialize?
val examples: Map<String, String>? = null, // needs to be mutually exclusive with example
val encoding: Map<String, String>? = null // todo encoding object -> https://swagger.io/specification/#encoding-object

View File

@ -3,8 +3,8 @@ package org.leafygreens.kompendium.models
import java.net.URI
data class OpenApiSpecOAuthFlow(
val authorizationUrl: URI,
val tokenUrl: URI,
val refreshUrl: URI,
val scopes: Map<String, String>
val authorizationUrl: URI? = null,
val tokenUrl: URI? = null,
val refreshUrl: URI? = null,
val scopes: Map<String, String>? = null
)

View File

@ -8,10 +8,12 @@ data class OpenApiSpecPathItemOperation(
val operationId: String? = null,
val parameters: List<OpenApiSpecReferencable>? = null,
val requestBody: OpenApiSpecReferencable? = null,
val responses: Map<String, OpenApiSpecReferencable>? = null, // TODO How to enforce `default` requirement
// TODO How to enforce `default` requirement 🧐
val responses: Map<String, OpenApiSpecReferencable>? = null,
val callbacks: Map<String, OpenApiSpecReferencable>? = null,
val deprecated: Boolean = false,
val security: List<Map<String, List<String>>>? = null, // todo big yikes... also needs to reference objects in the security scheme 🤔
// todo big yikes... also needs to reference objects in the security scheme 🤔
val security: List<Map<String, List<String>>>? = null,
val servers: List<OpenApiSpecServer>? = null,
val `x-codegen-request-body-name`: String? = null
)

View File

@ -27,7 +27,10 @@ data class OpenApiSpecParameter(
val description: String?,
val required: Boolean = true,
val deprecated: Boolean = false,
val allowEmptyValue: Boolean = false
val allowEmptyValue: Boolean = false,
val style: String? = null,
val explode: Boolean? = false,
val schema: OpenApiSpecSchema? = null
) : OpenApiSpecReferencable()
data class OpenApiSpecRequest(

View File

@ -0,0 +1,31 @@
package org.leafygreens.kompendium.models
sealed class OpenApiSpecSchema
sealed class OpenApiSpecSchemaTyped(
val type: String,
) : OpenApiSpecSchema()
data class OpenApiSpecSchemaArray<T : OpenApiSpecSchema>(
val items: T
) : OpenApiSpecSchemaTyped("array")
data class OpenApiSpecSchemaString(
val default: String,
val `enum`: Set<String>? = null
) : OpenApiSpecSchemaTyped("string")
// TODO In Kt 1.5 Should be able to reference external sealed classes
data class OpenApiSpecSchemaRef(
val `$ref`: String
) : OpenApiSpecSchema()
data class OpenApiSpecSchemaSecurity(
val type: String? = null, // TODO Enum? "apiKey", "http", "oauth2", "openIdConnect"
val name: String? = null,
val `in`: String? = null,
val scheme: String? = null,
val flows: OpenApiSpecOAuthFlows? = null,
val bearerFormat: String? = null,
val description: String? = null,
) : OpenApiSpecSchema()

View File

@ -1,12 +0,0 @@
package org.leafygreens.kompendium.models
data class OpenApiSpecSecuritySchema(
val type: String, // TODO Enum? "apiKey", "http", "oauth2", "openIdConnect"
val name: String,
val `in`: String,
val scheme: String,
val flows: OpenApiSpecOAuthFlows,
val bearerFormat: String?,
val description: String?,
)

View File

@ -1,14 +0,0 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package kompendium
import kotlin.test.Test
import kotlin.test.assertEquals
class LibraryTest {
@Test fun testSomeLibraryMethod() {
val classUnderTest = Library()
assertEquals(classUnderTest.someLibraryMethod(), "Heya", "someLibraryMethod should return 'true'")
}
}

View File

@ -3,16 +3,23 @@ package org.leafygreens.kompendium.util
import java.io.File
import java.net.URI
import org.leafygreens.kompendium.models.OpenApiSpec
import org.leafygreens.kompendium.models.OpenApiSpecComponents
import org.leafygreens.kompendium.models.OpenApiSpecExternalDocumentation
import org.leafygreens.kompendium.models.OpenApiSpecInfo
import org.leafygreens.kompendium.models.OpenApiSpecInfoContact
import org.leafygreens.kompendium.models.OpenApiSpecInfoLicense
import org.leafygreens.kompendium.models.OpenApiSpecMediaType
import org.leafygreens.kompendium.models.OpenApiSpecOAuthFlow
import org.leafygreens.kompendium.models.OpenApiSpecOAuthFlows
import org.leafygreens.kompendium.models.OpenApiSpecParameter
import org.leafygreens.kompendium.models.OpenApiSpecPathItem
import org.leafygreens.kompendium.models.OpenApiSpecPathItemOperation
import org.leafygreens.kompendium.models.OpenApiSpecReferenceObject
import org.leafygreens.kompendium.models.OpenApiSpecRequest
import org.leafygreens.kompendium.models.OpenApiSpecResponse
import org.leafygreens.kompendium.models.OpenApiSpecSchemaArray
import org.leafygreens.kompendium.models.OpenApiSpecSchemaRef
import org.leafygreens.kompendium.models.OpenApiSpecSchemaSecurity
import org.leafygreens.kompendium.models.OpenApiSpecSchemaString
import org.leafygreens.kompendium.models.OpenApiSpecServer
import org.leafygreens.kompendium.models.OpenApiSpecTag
@ -26,7 +33,11 @@ object TestData {
val testSpec = OpenApiSpec(
info = OpenApiSpecInfo(
title = "Swagger Petstore",
description = "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
description = """
This is a sample server Petstore server. You can find out more about Swagger at
[http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).
For this sample, you can use the api key `special-key` to test the authorization filters.
""".trimIndent(),
termsOfService = URI("http://swagger.io/terms/"),
contact = OpenApiSpecInfoContact(
name = "Team Swag",
@ -82,10 +93,10 @@ object TestData {
description = "Pet object that needs to be added to the store",
content = mapOf(
"application/json" to OpenApiSpecMediaType(
schema = OpenApiSpecReferenceObject(`$ref` = "#/components/schemas/Pet")
schema = OpenApiSpecSchemaRef(`$ref` = "#/components/schemas/Pet")
),
"application/xml" to OpenApiSpecMediaType(
schema = OpenApiSpecReferenceObject(`$ref` = "#/components/schemas/Pet")
schema = OpenApiSpecSchemaRef(`$ref` = "#/components/schemas/Pet")
)
),
required = true
@ -119,10 +130,10 @@ object TestData {
description = "Pet object that needs to be added to the store",
content = mapOf(
"application/json" to OpenApiSpecMediaType(
schema = OpenApiSpecReferenceObject(`$ref` = "#/components/schemas/Pet")
schema = OpenApiSpecSchemaRef(`$ref` = "#/components/schemas/Pet")
),
"application/xml" to OpenApiSpecMediaType(
schema = OpenApiSpecReferenceObject(`$ref` = "#/components/schemas/Pet")
schema = OpenApiSpecSchemaRef(`$ref` = "#/components/schemas/Pet")
)
)
),
@ -139,6 +150,75 @@ object TestData {
),
`x-codegen-request-body-name` = "body"
)
),
"/pet/findByStatus" to OpenApiSpecPathItem(
get = OpenApiSpecPathItemOperation(
tags = setOf("pet"),
summary = "Find Pets by status",
description = "Multiple status values can be provided with comma separated strings",
operationId = "findPetsByStatus",
parameters = listOf(
OpenApiSpecParameter(
name = "status",
`in` = "query",
description = "Status values that need to be considered for filter",
required = true,
style = "form",
explode = true,
schema = OpenApiSpecSchemaArray(
items = OpenApiSpecSchemaString(
default = "available",
`enum` = setOf("available", "pending", "sold")
)
)
)
),
responses = mapOf(
"200" to OpenApiSpecResponse(
description = "successful operation",
content = mapOf(
"application/xml" to OpenApiSpecMediaType(
schema = OpenApiSpecSchemaArray(
items = OpenApiSpecSchemaRef("#/components/schemas/Pet")
)
),
"application/json" to OpenApiSpecMediaType(
schema = OpenApiSpecSchemaArray(
items = OpenApiSpecSchemaRef("#/components/schemas/Pet")
)
)
)
),
"400" to OpenApiSpecResponse(
description = "Invalid status value",
content = mapOf()
)
),
security = listOf(mapOf(
"petstore_auth" to listOf("write:pets", "read:pets")
))
)
)
),
components = OpenApiSpecComponents(
securitySchemes = mapOf(
"petstore_auth" to OpenApiSpecSchemaSecurity(
type = "oauth2",
flows = OpenApiSpecOAuthFlows(
implicit = OpenApiSpecOAuthFlow(
authorizationUrl = URI("http://petstore.swagger.io/oauth/dialog"),
scopes = mapOf(
"write:pets" to "modify pets in your account",
"read:pets" to "read your pets"
)
)
)
),
"api_key" to OpenApiSpecSchemaSecurity(
type = "apiKey",
name = "api_key",
`in` = "header"
)
)
)
)

View File

@ -3,7 +3,7 @@
"info" : {
"title" : "Swagger Petstore",
"version" : "1.0.0",
"description" : "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
"description" : "This is a sample server Petstore server. You can find out more about Swagger at\n[http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).\nFor this sample, you can use the api key `special-key` to test the authorization filters.",
"termsOfService" : "http://swagger.io/terms/",
"contact" : {
"name" : "Team Swag",
@ -93,9 +93,86 @@
} ],
"x-codegen-request-body-name" : "body"
}
},
"/pet/findByStatus" : {
"get" : {
"tags" : [ "pet" ],
"summary" : "Find Pets by status",
"description" : "Multiple status values can be provided with comma separated strings",
"operationId" : "findPetsByStatus",
"parameters" : [ {
"name" : "status",
"in" : "query",
"description" : "Status values that need to be considered for filter",
"required" : true,
"deprecated" : false,
"allowEmptyValue" : false,
"style" : "form",
"explode" : true,
"schema" : {
"items" : {
"default" : "available",
"enum" : [ "available", "pending", "sold" ],
"type" : "string"
},
"type" : "array"
}
} ],
"responses" : {
"200" : {
"description" : "successful operation",
"content" : {
"application/xml" : {
"schema" : {
"items" : {
"$ref" : "#/components/schemas/Pet"
},
"type" : "array"
}
},
"application/json" : {
"schema" : {
"items" : {
"$ref" : "#/components/schemas/Pet"
},
"type" : "array"
}
}
}
},
"400" : {
"description" : "Invalid status value",
"content" : { }
}
},
"deprecated" : false,
"security" : [ {
"petstore_auth" : [ "write:pets", "read:pets" ]
} ]
}
}
},
"components" : {
"securitySchemes" : {
"petstore_auth" : {
"type" : "oauth2",
"flows" : {
"implicit" : {
"authorizationUrl" : "http://petstore.swagger.io/oauth/dialog",
"scopes" : {
"write:pets" : "modify pets in your account",
"read:pets" : "read your pets"
}
}
}
},
"api_key" : {
"type" : "apiKey",
"name" : "api_key",
"in" : "header"
}
}
},
"security" : { },
"tags" : [ {
"name" : "pet",
"description" : "Everything about your Pets",

View File

@ -8,7 +8,6 @@ import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import kompendium.Library
fun main() {
embeddedServer(
@ -22,7 +21,7 @@ fun Application.mainModule() {
routing {
route("/") {
get {
call.respondText(Library().someLibraryMethod())
call.respondText("hi")
}
}
}