Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/samples-kotlin-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
- samples/server/others/kotlin-server/jaxrs-spec-array-response
- samples/server/petstore/kotlin-spring-cloud
- samples/server/petstore/kotlin-misk
- samples/server/petstore/kotlin-misk-config
# comment out due to gradle build failure
#- samples/server/petstore/kotlin-spring-default
# no build.gradle file
Expand Down
11 changes: 11 additions & 0 deletions bin/configs/kotlin-misk-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
generatorName: kotlin-misk
outputDir: samples/server/petstore/kotlin-misk-config
Comment thread
wing328 marked this conversation as resolved.
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-misk
validateSpec: false
additionalProperties:
hideGenerationTimestamp: "true"
moduleClassName: "PetStoreModule"
generateStubImplClasses: true
addModelMoshiJsonAnnotation: true
actionPathPrefix : "samplePrefix"
1 change: 0 additions & 1 deletion bin/configs/kotlin-misk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ generatorName: kotlin-misk
outputDir: samples/server/petstore/kotlin-misk
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can delete this one if its not required?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-misk
validateSpec: false
additionalProperties:
hideGenerationTimestamp: "true"
moduleClassName: "PetStoreModule"
5 changes: 4 additions & 1 deletion docs/generators/kotlin-misk.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl

| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|actionPathPrefix|Prefix for action path| ||
|addModelMoshiJsonAnnotation|Add a Moshi JSON adapter annotation to all model classes| |true|
|additionalModelTypeAnnotations|Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
|apiSuffix|suffix for api classes| |Api|
|artifactId|Generated artifact id (name of jar).| |null|
|artifactVersion|Generated artifact's package version.| |1.0.0|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |original|
|generateStubImplClasses|Generate Stub Impl Classes| |false|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|modelMutable|Create mutable models| |false|
|moduleClassName|Name of the generated module class| |OpenApiModule|
Expand Down Expand Up @@ -273,7 +276,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON||OAS2,OAS3
|JSON||OAS2,OAS3
|XML|✗|OAS2,OAS3
|PROTOBUF|✓|ToolingExtension
|Custom|✗|OAS2,OAS3
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,28 @@

public class KotlinMiskServerCodegen extends AbstractKotlinCodegen implements BeanValidationFeatures {

private final Logger LOGGER = LoggerFactory.getLogger(KotlinMiskServerCodegen.class);

public static final String MODULE_CLASS_NAME = "moduleClassName";
public static final String ACTION_PATH_PREFIX = "actionPathPrefix";

private final Logger LOGGER = LoggerFactory.getLogger(KotlinMiskServerCodegen.class);
private static final String ROOT_PACKAGE = "rootPackage";
public static final String GENERATE_STUB_IMPL_CLASSES = "generateStubImplClasses";
public static final String ADD_MODEL_MOSHI_JSON_ANNOTATION = "addModelMoshiJsonAnnotation";

private boolean useBeanValidation = true;

@Setter
private boolean generateStubImplClasses = false;

@Setter
private boolean addModelMoshiJsonAnnotation = true;

protected String rootPackage = "org.openapitools.server.api";
protected String apiVersion = "1.0.0-SNAPSHOT";

@Setter protected String moduleClassName = "OpenApiModule";
@Setter protected String actionPathPrefix = "";

@Override
public CodegenType getTag() {
Expand All @@ -78,10 +89,12 @@ public KotlinMiskServerCodegen() {
super();

addSwitch(USE_BEANVALIDATION, "Use BeanValidation API annotations to validate data types", useBeanValidation);
addSwitch(GENERATE_STUB_IMPL_CLASSES, "Generate Stub Impl Classes", generateStubImplClasses);
addSwitch(ADD_MODEL_MOSHI_JSON_ANNOTATION, "Add a Moshi JSON adapter annotation to all model classes", addModelMoshiJsonAnnotation);

modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.PROTOBUF))
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.PROTOBUF))
.securityFeatures(EnumSet.noneOf(
SecurityFeature.class
))
Expand All @@ -108,6 +121,7 @@ public KotlinMiskServerCodegen() {
outputFolder = "generated-code" + File.separator + "kotlin-misk";

addOption(MODULE_CLASS_NAME, "Name of the generated module class", moduleClassName);
addOption(ACTION_PATH_PREFIX, "Prefix for action path", actionPathPrefix);

apiTestTemplateFiles.clear();
apiTestTemplateFiles.put("api_test.mustache", ".kt");
Expand All @@ -122,8 +136,12 @@ public KotlinMiskServerCodegen() {

apiTemplateFiles.clear();
apiTemplateFiles.put("apiAction.mustache", "Action.kt");
apiTemplateFiles.put("apiImpl.mustache", "Impl.kt");
apiTemplateFiles.put("apiInterface.mustache", ".kt");

if (generateStubImplClasses) {
apiTemplateFiles.put("apiImpl.mustache", "Impl.kt");
apiTemplateFiles.put("apiInterface.mustache", ".kt");
}

modelTemplateFiles.put("model.mustache", ".kt");

apiPackage = rootPackage + ".api";
Expand All @@ -148,13 +166,27 @@ public void processOpts() {
if (additionalProperties.containsKey(MODULE_CLASS_NAME)) {
setModuleClassName((String) additionalProperties.get(MODULE_CLASS_NAME));
}
additionalProperties.put(MODULE_CLASS_NAME, moduleClassName);
writePropertyBack(MODULE_CLASS_NAME, moduleClassName);

if (additionalProperties.containsKey(ACTION_PATH_PREFIX)) {
setActionPathPrefix((String) additionalProperties.get(ACTION_PATH_PREFIX));
}
writePropertyBack(ACTION_PATH_PREFIX, actionPathPrefix);

if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
this.setUseBeanValidation(convertPropertyToBoolean(USE_BEANVALIDATION));
}
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);

if (additionalProperties.containsKey(GENERATE_STUB_IMPL_CLASSES)) {
setGenerateStubImplClasses(convertPropertyToBoolean(GENERATE_STUB_IMPL_CLASSES));
}
writePropertyBack(GENERATE_STUB_IMPL_CLASSES, generateStubImplClasses);

if (additionalProperties.containsKey(ADD_MODEL_MOSHI_JSON_ANNOTATION)) {
setAddModelMoshiJsonAnnotation(convertPropertyToBoolean(ADD_MODEL_MOSHI_JSON_ANNOTATION));
}
writePropertyBack(ADD_MODEL_MOSHI_JSON_ANNOTATION, addModelMoshiJsonAnnotation);
applyJakartaPackage();

String apiModuleFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
Expand Down Expand Up @@ -211,6 +243,7 @@ private static Map<String, String> getMappings() {
result.put("application/grpc", "MediaTypes.APPLICATION_GRPC");
result.put("application/javascript", "MediaTypes.APPLICATION_JAVASCRIPT");
result.put("application/json", "MediaTypes.APPLICATION_JSON");
result.put("application/jwt", "MediaTypes.APPLICATION_JWT");
result.put("application/octetstream", "MediaTypes.APPLICATION_OCTETSTREAM");
result.put("application/pdf", "MediaTypes.APPLICATION_OCTETSTREAM");
result.put("application/x-protobuf", "MediaTypes.APPLICATION_PROTOBUF");
Expand All @@ -219,10 +252,11 @@ private static Map<String, String> getMappings() {
result.put("application/zip", "MediaTypes.APPLICATION_ZIP");

result.put("image/gif", "MediaTypes.IMAGE_GIF");
result.put("image/x-icon", "MediaTypes.IMAGE_ICO");
result.put("image/jpeg", "MediaTypes.IMAGE_JPEG");
result.put("image/png", "MediaTypes.IMAGE_PNG");
result.put("image/svg+xml", "MediaTypes.IMAGE_SVG");
result.put("image/x-icon", "MediaTypes.IMAGE_ICO");
result.put("image/tiff", "MediaTypes.IMAGE_TIFF");

result.put("multipart/form-data", "MediaTypes.FORM_DATA");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@ import misk.web.mediatype.MediaTypes
{{#imports}}import {{import}}
{{/imports}}

{{#operations}}
/**
* Generated file, please change {{classname}}Impl.
*/
* @TODO("Fill out implementation")
*/
{{#operations}}
@Singleton
class {{classname}}Action @Inject constructor(
private val {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}
) : WebAction, {{classname}} {
) : WebAction {
{{#operation}}

@{{httpMethod}}("{{path}}")
@{{httpMethod}}("{{actionPathPrefix}}{{path}}")
@Description("{{{summary}}}"){{#hasConsumes}}
@RequestContentType({{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}){{/hasConsumes}}{{#hasProduces}}
@ResponseContentType({{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}}
@LogRequestResponse(bodySampling = 1.0, errorBodySampling = 1.0)
override fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
fun {{operationId}}({{#allParams}}
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
TODO()
}
{{/operation}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class {{classname}}Impl @Inject constructor(
): {{classname}} {
{{#operation}}

override fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
override fun {{operationId}}({{#allParams}}
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
TODO()
}
{{/operation}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import misk.web.RequestHeader
interface {{classname}} {
{{#operation}}

fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}}
fun {{operationId}}({{#allParams}}
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}: {{{returnType}}}{{/returnType}} {
{{/operation}}
}
{{/operations}}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import misk.web.RequestHeader
@MiskTest(startService = true)
internal class {{classname}}Test {

@Inject private lateinit var {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}
@Inject private lateinit var {{#lambda.camelcase}}{{classname}}{{/lambda.camelcase}}: {{classname}}Action

{{#operations}}
{{#operation}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ version = "{{artifactVersion}}"

dependencies {
implementation("jakarta.validation:jakarta.validation-api:3.1.1")
implementation("com.squareup.misk:misk:2025.04.02.195630-a61d550")
//implementation("com.squareup.wire:wire-runtime:5.2.1")
implementation("com.squareup.misk:misk:2025.04.27.230742-6035cb3")
implementation("com.squareup.moshi:moshi:1.15.2")

testImplementation("com.squareup.misk:misk-testing:2025.02.11.123913-8a41324")
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package {{modelPackage}}
{{#imports}}
import {{import}}
{{/imports}}

{{#models}}
{{#model}}
{{#isEnum}}
Expand All @@ -16,6 +15,9 @@ enum class {{classname}} {
}
{{/isEnum}}
{{^isEnum}}
{{#addModelMoshiJsonAnnotation}}import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true){{/addModelMoshiJsonAnnotation}}
data class {{classname}}(
{{#vars}}
{{#description}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,8 @@ protected void verifyOptions() {
verify(codegen).setAdditionalModelTypeAnnotations(List.of(KotlinMiskServerCodegenOptionsProvider.ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE));
verify(codegen).setUseBeanValidation(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.USE_BEAN_VALIDATION));
verify(codegen).setModuleClassName(KotlinMiskServerCodegenOptionsProvider.MODULE_CLASS_NAME);
verify(codegen).setActionPathPrefix(KotlinMiskServerCodegenOptionsProvider.ACTION_PATH_PREFIX);
verify(codegen).setGenerateStubImplClasses(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.GENERATE_STUB_IMPL_CLASSES));
verify(codegen).setAddModelMoshiJsonAnnotation(Boolean.valueOf(KotlinMiskServerCodegenOptionsProvider.ADD_MODEL_MOSHI_JSON_ANNOTATION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public void testDefaultConfiguration() {
Assert.assertEquals(codegen.apiPackage(), "org.openapitools.server.api.api");
Assert.assertEquals(codegen.modelPackage(), "org.openapitools.server.api.model");

// Test PROTOBUF wire format
// Test wire formats
Assert.assertTrue(codegen.getFeatureSet().getWireFormatFeatures().contains(WireFormatFeature.JSON));
Assert.assertTrue(codegen.getFeatureSet().getWireFormatFeatures().contains(WireFormatFeature.PROTOBUF));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ public class KotlinMiskServerCodegenOptionsProvider implements OptionsProvider {
public static final String API_SUFFIX_VALUE = "Api";
public static final String ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE = "";
public static final String USE_BEAN_VALIDATION = "false";
public static final String GENERATE_STUB_IMPL_CLASSES = "false";
public static final String ADD_MODEL_MOSHI_JSON_ANNOTATION = "true";
public static final String MODULE_CLASS_NAME = "OpenApiModule";
public static final String ACTION_PATH_PREFIX = "samplePrefix";

@Override
public String getLanguage() {
Expand Down Expand Up @@ -51,6 +54,9 @@ public Map<String, String> createOptions() {
ADDITIONAL_MODEL_TYPE_ANNOTATIONS_VALUE)
.put(KotlinMiskServerCodegen.MODULE_CLASS_NAME, MODULE_CLASS_NAME)
.put(BeanValidationFeatures.USE_BEANVALIDATION, USE_BEAN_VALIDATION)
.put(KotlinMiskServerCodegen.ACTION_PATH_PREFIX, ACTION_PATH_PREFIX)
.put(KotlinMiskServerCodegen.ADD_MODEL_MOSHI_JSON_ANNOTATION, ADD_MODEL_MOSHI_JSON_ANNOTATION)
.put(KotlinMiskServerCodegen.GENERATE_STUB_IMPL_CLASSES, GENERATE_STUB_IMPL_CLASSES)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
README.md
build.gradle.kts
docs/ApiResponse.md
docs/Category.md
docs/Order.md
docs/Pet.md
docs/PetApi.md
docs/StoreApi.md
docs/Tag.md
docs/User.md
docs/UserApi.md
settings.gradle.kts
src/main/kotlin/org/openapitools/server/api/api/PetApiAction.kt
src/main/kotlin/org/openapitools/server/api/api/PetStoreModule.kt
src/main/kotlin/org/openapitools/server/api/api/StoreApiAction.kt
src/main/kotlin/org/openapitools/server/api/api/UserApiAction.kt
src/main/kotlin/org/openapitools/server/api/model/Category.kt
src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt
src/main/kotlin/org/openapitools/server/api/model/Order.kt
src/main/kotlin/org/openapitools/server/api/model/Pet.kt
src/main/kotlin/org/openapitools/server/api/model/Tag.kt
src/main/kotlin/org/openapitools/server/api/model/User.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7.14.0-SNAPSHOT
Loading
Loading