diff --git a/bin/kotlin-vertx-server-petstore.sh b/bin/kotlin-vertx-server-petstore.sh new file mode 100755 index 000000000000..73d0d087f3bd --- /dev/null +++ b/bin/kotlin-vertx-server-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=$(ls -ld "$SCRIPT") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=$(dirname "$SCRIPT")/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=$(dirname "$SCRIPT")/.. + APP_DIR=$(cd "${APP_DIR}"; pwd) +fi + +executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g kotlin-vertx -o samples/server/petstore/kotlin/vertx" + +java ${JAVA_OPTS} -jar ${executable} ${ags} diff --git a/bin/windows/kotlin-vertx-server-petstore.bat b/bin/windows/kotlin-vertx-server-petstore.bat new file mode 100644 index 000000000000..6fd12f43d82c --- /dev/null +++ b/bin/windows/kotlin-vertx-server-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties +set ags=generate --artifact-id "kotlin-vertx-petstore-server" -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g kotlin-vertx -o samples\server\petstore\kotlin\vertx + +java %JAVA_OPTS% -jar %executable% %ags% diff --git a/docs/generators.md b/docs/generators.md index 2bb9b1f5e28e..808b3cc5cb42 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -95,6 +95,7 @@ The following generators are available: * [jaxrs-spec](generators/jaxrs-spec) * [kotlin-server](generators/kotlin-server) * [kotlin-spring](generators/kotlin-spring) +* [korlin-vertx](generators/kotlin-vertx) * [nodejs-express-server (beta)](generators/nodejs-express-server) * [nodejs-server-deprecated (deprecated)](generators/nodejs-server-deprecated) * [php-laravel](generators/php-laravel) diff --git a/docs/generators/kotlin-vertx.md b/docs/generators/kotlin-vertx.md new file mode 100644 index 000000000000..6759792afbf8 --- /dev/null +++ b/docs/generators/kotlin-vertx.md @@ -0,0 +1,18 @@ + +--- +id: generator-opts-server-kotlin-vertx +title: Config Options for kotlin-vertx +sidebar_label: kotlin-vertx +--- + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|sourceFolder|source folder for generated code| |src/main/kotlin| +|modelPackage|package for generated models| |org.openapitools.server.api.model| +|apiPackage|package for generated api classes| |org.openapitools.server.api.verticle| +|apiSuffix|suffix for api classes| |Api| +|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|artifactId|Generated artifact id (name of jar).| |kotlin-server| +|artifactVersion|Generated artifact's package version.| |1.0.0| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase| +|parcelizeModels|toggle "@Parcelize" for generated models| |null| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java new file mode 100644 index 000000000000..19863e9a67b8 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -0,0 +1,85 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.languages; + +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenType; +import org.openapitools.codegen.SupportingFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Locale; + +public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { + + protected String rootPackage = "org.openapitools.server.api"; + protected String apiVersion = "1.0.0-SNAPSHOT"; + + public static final String ROOT_PACKAGE = "rootPackage"; + + public static final String PROJECT_NAME = "projectName"; + + static Logger LOGGER = LoggerFactory.getLogger(KotlinVertxServerCodegen.class); + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "kotlin-vertx"; + } + + public String getHelp() { + return "Generates a kotlin-vertx server."; + } + + public KotlinVertxServerCodegen() { + super(); + + outputFolder = "generated-code" + File.separator + "kotlin-vertx"; + modelTemplateFiles.put("model.mustache", ".kt"); + + apiTestTemplateFiles.clear(); + modelDocTemplateFiles.clear(); + supportingFiles.clear(); + + apiTemplateFiles.clear(); + apiTemplateFiles.put("api.mustache", ".kt"); + apiTemplateFiles.put("apiProxy.mustache", "VertxProxyHandler.kt"); + apiTemplateFiles.put("api_verticle.mustache","Verticle.kt"); + + embeddedTemplateDir = templateDir = "kotlin-vertx-server"; + apiPackage = rootPackage + ".verticle"; + modelPackage = rootPackage + ".model"; + artifactId = "openapi-kotlin-vertx-server"; + artifactVersion = apiVersion; + + updateOption(CodegenConstants.API_PACKAGE, apiPackage); + updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage); + additionalProperties.put(ROOT_PACKAGE, rootPackage); + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + + } + + @Override + public String escapeReservedWord(String name) { + return name; + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index dcd64831edc6..5a6cb16c1ac2 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -28,6 +28,7 @@ org.openapitools.codegen.languages.ErlangClientCodegen org.openapitools.codegen.languages.ErlangProperCodegen org.openapitools.codegen.languages.ErlangServerCodegen org.openapitools.codegen.languages.FlashClientCodegen +org.openapitools.codegen.languages.FsharpGiraffeServerCodegen org.openapitools.codegen.languages.GoClientCodegen org.openapitools.codegen.languages.GoClientExperimentalCodegen org.openapitools.codegen.languages.GoServerCodegen @@ -38,6 +39,7 @@ org.openapitools.codegen.languages.GroovyClientCodegen org.openapitools.codegen.languages.KotlinClientCodegen org.openapitools.codegen.languages.KotlinServerCodegen org.openapitools.codegen.languages.KotlinSpringServerCodegen +org.openapitools.codegen.languages.KotlinVertxServerCodegen org.openapitools.codegen.languages.HaskellHttpClientCodegen org.openapitools.codegen.languages.HaskellServantCodegen org.openapitools.codegen.languages.JavaClientCodegen @@ -114,5 +116,4 @@ org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen org.openapitools.codegen.languages.TypeScriptNodeClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen org.openapitools.codegen.languages.FsharpGiraffeServerCodegen - org.openapitools.codegen.languages.AsciidocDocumentationCodegen diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache new file mode 100644 index 000000000000..f4db05742d00 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache @@ -0,0 +1,76 @@ +# {{packageName}} - Kotlin Server library for {{appName}} + +## Requires + +* Kotlin 1.3.10 +* Maven 3.3 + +## Build + +``` +mvn clean package +``` + +This runs all tests and packages the library. + +## Features/Implementation Notes + +* Supports JSON inputs/outputs and Form inputs. +* Supports collection formats for query parameters: csv, tsv, ssv, pipes. +* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. + +{{#generateApiDocs}} + + ## Documentation for API Endpoints + + All URIs are relative to *{{{basePath}}}* + + Class | Method | HTTP request | Description + ------------ | ------------- | ------------- | ------------- + {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}} + {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +{{/generateApiDocs}} + +{{#generateModelDocs}} + + ## Documentation for Models + + {{#modelPackage}} + {{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) + {{/model}}{{/models}} + {{/modelPackage}} + {{^modelPackage}} + No model defined in this package + {{/modelPackage}} +{{/generateModelDocs}} + +{{! TODO: optional documentation for authorization? }} +## Documentation for Authorization + +{{^authMethods}} + All endpoints do not require authorization. +{{/authMethods}} +{{#authMethods}} + {{#last}} + Authentication schemes defined for the API: + {{/last}} +{{/authMethods}} +{{#authMethods}} + + ### {{name}} + + {{#isApiKey}}- **Type**: API key + - **API key parameter name**: {{keyParamName}} + - **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} + {{/isApiKey}} + {{#isBasic}}- **Type**: HTTP basic authentication + {{/isBasic}} + {{#isOAuth}}- **Type**: OAuth + - **Flow**: {{flow}} + - **Authorization URL**: {{authorizationUrl}} + - **Scopes**: {{^scopes}}N/A{{/scopes}} + {{#scopes}} - {{scope}}: {{description}} + {{/scopes}} + {{/isOAuth}} + +{{/authMethods}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache new file mode 100644 index 000000000000..279271960743 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -0,0 +1,53 @@ +package {{package}} + +{{#imports}}import {{import}} +{{/imports}} +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray +import com.github.wooyme.openapi.Response +import io.vertx.ext.web.api.OperationRequest +import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory +import io.vertx.serviceproxy.ServiceBinder +import io.vertx.ext.web.handler.CookieHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.LocalSessionStore +import java.util.List +import java.util.Map + + +interface {{classname}} { + fun init(vertx:Vertx,config:JsonObject) +{{#operations}} + {{#operation}} + /* {{operationId}} + * {{summary}} */ + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}kotlin.collections.List{{/isFile}}{{^isRequired}}?{{/isRequired}},{{/allParams}}context:OperationRequest):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + {{/operation}} +{{/operations}} + companion object { + const val address = "{{classname}}-service" + suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) + routerFactory.addGlobalHandler(CookieHandler.create()) + routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.setExtraOperationContextPayloadMapper{ + JsonObject().put("files",JsonArray(it.fileUploads().map { it.uploadedFileName() })) + } + val opf = routerFactory::class.java.getDeclaredField("operations") + opf.isAccessible = true + val operations = opf.get(routerFactory) as Map + for (m in {{classname}}::class.java.methods) { + val methodName = m.name + val op = operations[methodName] + if (op != null) { + val method = op::class.java.getDeclaredMethod("mountRouteToService",String::class.java,String::class.java) + method.isAccessible = true + method.invoke(op,address,methodName) + } + } + routerFactory.mountServiceInterface({{classname}}::class.java, address) + return routerFactory + } + } +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache new file mode 100644 index 000000000000..8c6f81f1b43f --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache @@ -0,0 +1,179 @@ +package {{package}} + +import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.api.OperationRequest +import io.vertx.ext.web.api.OperationResponse +import io.vertx.ext.web.api.generator.ApiHandlerUtils +import io.vertx.serviceproxy.ProxyHandler +import io.vertx.serviceproxy.ServiceException +import io.vertx.serviceproxy.ServiceExceptionMessageCodec +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import com.google.gson.reflect.TypeToken +import com.google.gson.Gson +{{#imports}}import {{import}} +{{/imports}} + +class {{classname}}VertxProxyHandler(private val vertx: Vertx, private val service: {{classname}}, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { + private val timerID: Long + private var lastAccessed: Long = 0 + init { + try { + this.vertx.eventBus().registerDefaultCodec(ServiceException::class.java, + ServiceExceptionMessageCodec()) + } catch (ex: IllegalStateException) {} + + if (timeoutSeconds != (-1).toLong() && !topLevel) { + var period = timeoutSeconds * 1000 / 2 + if (period > 10000) { + period = 10000 + } + this.timerID = vertx.setPeriodic(period) { this.checkTimedOut(it) } + } else { + this.timerID = -1 + } + accessed() + } + private fun checkTimedOut(id: Long) { + val now = System.nanoTime() + if (now - lastAccessed > timeoutSeconds * 1000000000) { + close() + } + } + + override fun close() { + if (timerID != (-1).toLong()) { + vertx.cancelTimer(timerID) + } + super.close() + } + + private fun accessed() { + this.lastAccessed = System.nanoTime() + } + override fun handle(msg: Message) { + try { + val json = msg.body() + val action = msg.headers().get("action") ?: throw IllegalStateException("action not specified") + accessed() + val contextSerialized = json.getJsonObject("context") ?: throw IllegalStateException("Received action $action without OperationRequest \"context\"") + val context = OperationRequest(contextSerialized) + when (action) { + {{#operations}}{{#operation}} + "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}" -> { + {{#hasParams}} + val params = context.params + {{#allParams}} + {{#isListContainer}} + val {{paramName}}Param = ApiHandlerUtils.searchJsonArrayInJson(params,"{{#isBodyParam}}body{{/isBodyParam}}{{^isBodyParam}}{{baseName}}{{/isBodyParam}}") + {{#required}} + if({{paramName}}Param == null){ + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() + , object : TypeToken>(){}.type) + {{/required}} + {{^required}} + val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} + else Gson().fromJson({{paramName}}Param.encode(), + , object : TypeToken>(){}.type) + {{/required}} + {{/isListContainer}} + {{^isListContainer}} + {{#isFile}} + val {{paramName}}Param = context.extra.getJsonArray("files") + {{#required}} + if ({{paramName}}Param == null) { + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}} = {{paramName}}Param.map{ java.io.File(it as String) } + {{/required}} + {{^required}} + val {{paramName}} = {{paramName}}Param?.map{ java.io.File(it as String) } + {{/required}} + {{/isFile}} + {{#isPrimitiveType}} + {{#isString}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isString}} + {{#isDate}} + val {{paramName}} = java.time.LocalDate.parse(ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")) + {{/isDate}} + {{#isDateTime}} + val {{paramName}} = java.time.LocalDateTime.parse(ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")) + {{/isDateTime}} + {{#isEmail}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isEmail}} + {{#isUuid}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isUuid}} + {{#isNumber}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isNumber}} + {{#isLong}} + val {{paramName}} = ApiHandlerUtils.searchLongInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isLong}} + {{#isInteger}} + val {{paramName}} = ApiHandlerUtils.searchIntegerInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isInteger}} + {{#isFloat}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toFloat() + {{/isFloat}} + {{#isDouble}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isDouble}} + {{#isBoolean}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toBoolean() + {{/isBoolean}} + {{#isFreeFormObject}} + val {{paramName}} = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isFreeFormObject}} + {{#required}} + if({{paramName}} == null){ + throw IllegalArgumentException("{{paramName}} is required") + } + {{/required}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + val {{paramName}}Param = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} + if ({{paramName}}Param == null) { + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} + {{^required}} + val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} + {{/isPrimitiveType}} + {{/isListContainer}} + {{/allParams}} + GlobalScope.launch(vertx.dispatcher()){ + val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}},{{/allParams}}{{/hasParams}}context) + {{#isListContainer}} + val payload = JsonArray(Json.encode(result.payload)).toBuffer() + {{/isListContainer}} + {{^isListContainer}} + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + {{/isListContainer}} + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + {{/hasParams}} + } + {{/operation}}{{/operations}} + } + }catch (t: Throwable) { + msg.reply(ServiceException(500, t.message)) + throw t + } + } +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache new file mode 100644 index 000000000000..5a41503df5b9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache @@ -0,0 +1,42 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#generateModelDocs}}[**{{dataType}}**]({{baseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{dataType}}**{{/generateModelDocs}}{{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#generateModelDocs}}[**{{returnType}}**]({{returnBaseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{returnType}}**{{/generateModelDocs}}{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache new file mode 100644 index 000000000000..c168d12e03a3 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache @@ -0,0 +1,19 @@ +package {{package}} +import io.vertx.core.Vertx +import io.vertx.core.AbstractVerticle +import io.vertx.serviceproxy.ServiceBinder + +fun main(){ + Vertx.vertx().deployVerticle({{classname}}Verticle()) +} + +class {{classname}}Verticle:AbstractVerticle() { + + override fun start() { + val instance = (javaClass.classLoader.loadClass("{{package}}.{{classname}}Impl").newInstance() as {{classname}}) + instance.init(vertx,config()) + ServiceBinder(vertx) + .setAddress({{classname}}.address) + .register({{classname}}::class.java,instance) + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache new file mode 100644 index 000000000000..b363fc5a61f2 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache @@ -0,0 +1,15 @@ +# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**inline**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + +{{!NOTE: see java's resources "pojo_doc.mustache" once enums are fully implemented}} +## Enum: {{baseName}} +Name | Value +---- | -----{{#allowableValues}} +{{name}} | {{#values}}{{.}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}} +{{/isEnum}}{{/vars}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache new file mode 100644 index 000000000000..d4c099d64ea7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache @@ -0,0 +1,42 @@ + +{{#parcelizeModels}} +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize +{{/parcelizeModels}} +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * {{{description}}} +{{#vars}} + * @param {{name}} {{{description}}} +{{/vars}} + */ +{{#parcelizeModels}} +@Parcelize +{{/parcelizeModels}} +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class {{classname}} ( +{{#requiredVars}} +{{>data_class_req_var}}{{^-last}}, +{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}}, +{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}}, +{{/-last}}{{/optionalVars}} +){{#parcelizeModels}} : Parcelable{{/parcelizeModels}} { +{{#hasEnums}}{{#vars}}{{#isEnum}} + /** + * {{{description}}} + * Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} + */ + enum class {{nameInCamelCase}}(val value: {{dataType}}){ + {{#allowableValues}}{{#enumVars}} + {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} + {{/enumVars}}{{/allowableValues}} + } +{{/isEnum}}{{/vars}}{{/hasEnums}} + {{#requiredVars}} + var {{{name}}} get() = _{{{name}}} ?: throw IllegalArgumentException("{{{name}}} is required") + set(value){ _{{{name}}} = value } + {{/requiredVars}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache new file mode 100644 index 000000000000..809b00758683 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache @@ -0,0 +1,4 @@ +{{#description}} + /* {{{description}}} */ +{{/description}} + var {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache new file mode 100644 index 000000000000..66ec56120bea --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache @@ -0,0 +1,4 @@ +{{#description}} + /* {{{description}}} */ +{{/description}} + @SerializedName("{{{name}}}") private var _{{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache new file mode 100644 index 000000000000..0867107d9930 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache @@ -0,0 +1,17 @@ + + public enum {{{datatypeWithEnum}}} { + {{#allowableValues}}{{#enumVars}}{{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private String value; + + {{{datatypeWithEnum}}}(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache new file mode 100644 index 000000000000..791398b97894 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache @@ -0,0 +1,9 @@ +/** +* {{{description}}} +* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} +*/ +enum class {{classname}}(val value: {{dataType}}){ +{{#allowableValues}}{{#enumVars}} + {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} +{{/enumVars}}{{/allowableValues}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache new file mode 100644 index 000000000000..fcb3d7e61aa6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache @@ -0,0 +1,7 @@ +# {{classname}} + +## Enum + +{{#allowableValues}}{{#enumVars}} + * `{{name}}` (value: `{{{value}}}`) +{{/enumVars}}{{/allowableValues}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache new file mode 100644 index 000000000000..3a547de74bb7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache @@ -0,0 +1,11 @@ +/** +* {{{appName}}} +* {{{appDescription}}} +* +* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} +* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache new file mode 100644 index 000000000000..74b63c00c6f5 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache @@ -0,0 +1,11 @@ +{{>licenseInfo}} +package {{modelPackage}} + +{{#imports}}import {{import}} +{{/imports}} + +{{#models}} + {{#model}} + {{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}}{{>data_class}}{{/isEnum}} + {{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache new file mode 100644 index 000000000000..08a7b3496ab3 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache @@ -0,0 +1,190 @@ + + 4.0.0 + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + jar + + {{appName}} + + + UTF-8 + 1.8 + 1.3.10 + true + 4.12 + 3.4.1 + 3.3 + 1.0.2 + 2.3 + 2.7.4 + 3.6.0 + + + + + junit + junit + ${junit.version} + test + + + + io.vertx + vertx-unit + ${vertx.version} + test + + + + com.github.wooyme + vertx-openapi-router + ${vertx-openapi-router.version} + + + + com.google.code.gson + gson + 2.8.5 + + + + javax.annotation + javax.annotation-api + 1.2 + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + RELEASE + + + + io.vertx + vertx-core + ${vertx.version} + + + io.vertx + vertx-web + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin-coroutines + ${vertx.version} + + + + io.swagger.parser.v3 + swagger-parser + 2.0.5 + + + + io.vertx + vertx-web-api-contract + ${vertx.version} + + + + io.vertx + vertx-service-proxy + ${vertx.version} + + + + io.vertx + vertx-web-api-service + ${vertx.version} + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + 1.8 + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + + 1.8 + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + {{apiPackage}}.DefaultApiVerticleKt + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar + + + + + + + \ No newline at end of file