Skip to content

Commit

Permalink
Add OpenApiV2Emitter (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
wilmveel authored Nov 20, 2023
1 parent 63e2b69 commit 427a003
Show file tree
Hide file tree
Showing 17 changed files with 312 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import community.flock.wirespec.compiler.core.emit.common.Emitter;
import community.flock.wirespec.compiler.core.parse.nodes.Node;
import community.flock.wirespec.compiler.core.parse.nodes.Refined;
import community.flock.wirespec.compiler.core.parse.nodes.Type;
import community.flock.wirespec.compiler.core.parse.nodes.Endpoint;
import community.flock.wirespec.compiler.core.parse.nodes.Enum;
import community.flock.wirespec.compiler.utils.Logger;
import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
Expand All @@ -15,66 +12,21 @@

public class CustomEmitter extends Emitter {

public CustomEmitter(Logger logger, boolean split) {
public CustomEmitter(@NotNull Logger logger, boolean split) {
super(logger, split);
}

@NotNull
@Override
public String getShared() {
return "";
}

@Override
public List<Pair<String, String>> emit(List<? extends Node> ast) {
return super.emit(ast)
public List<Pair<String, String>> emit(@NotNull List<? extends Node> ast) {
return ast
.stream()
.map(a -> new Pair<String,String>(a.component1(), "package hello;\n\n" + a.component2()))
.filter(sc -> sc instanceof Type)
.map (sc -> emit((Type) sc))
.collect(Collectors.toList());
}

@Override
public String emit(Refined refined) {
return null;
}

@Override
public String emit(Enum enumm) {
return null;
public Pair<String,String> emit(Type type) {
return new Pair<>(type.getName(), "package hello;\n\npublic class " + type.getName() + " {}");
}

@Override
public String emit(Refined.Validator validator) {
return null;
}

@Override
public String emit(Type type) {
return "public class " + type.getName() + " {}";
}

@Override
public String emit(Type.Shape shape) {
return null;
}

@Override
public String emit(Type.Shape.Field field) {
return null;
}

@Override
public String emit(Type.Shape.Field.Identifier identifier) {
return null;
}

@Override
public String emit(Type.Shape.Field.Reference reference) {
return null;
}

@Override
public String emit(Endpoint endpoint) {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package community.flock.wirespec.compiler.cli

import arrow.core.Either
import community.flock.wirespec.compiler.cli.Language.*
import community.flock.wirespec.compiler.cli.Language.Jvm.Java
import community.flock.wirespec.compiler.cli.Language.Jvm.Kotlin
import community.flock.wirespec.compiler.cli.Language.Jvm.Scala
import community.flock.wirespec.compiler.cli.Language.OpenApi.*
import community.flock.wirespec.compiler.cli.Language.Script.TypeScript
import community.flock.wirespec.compiler.cli.Language.Script.Wirespec
import community.flock.wirespec.compiler.cli.io.Directory
Expand All @@ -19,10 +21,12 @@ import community.flock.wirespec.compiler.cli.io.WirespecFile
import community.flock.wirespec.compiler.core.compile
import community.flock.wirespec.compiler.core.emit.JavaEmitter
import community.flock.wirespec.compiler.core.emit.KotlinEmitter
import community.flock.wirespec.compiler.core.emit.OpenApiV2Emitter
import community.flock.wirespec.compiler.core.emit.ScalaEmitter
import community.flock.wirespec.compiler.core.emit.TypeScriptEmitter
import community.flock.wirespec.compiler.core.emit.WirespecEmitter
import community.flock.wirespec.compiler.core.emit.common.DEFAULT_PACKAGE_NAME
import community.flock.wirespec.compiler.core.emit.common.AbstractEmitter
import community.flock.wirespec.compiler.core.emit.common.Emitter
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.orNull
Expand All @@ -41,8 +45,9 @@ private enum class OpenapiVersion {
private sealed interface Language {
enum class Jvm : Language { Java, Kotlin, Scala }
enum class Script : Language { TypeScript, Wirespec }
enum class OpenApi : Language { OpenApiV2, OpenApiV3 }
companion object {
fun values(): List<Enum<*>> = Jvm.entries + Script.entries
fun values(): List<Enum<*>> = Jvm.entries + Script.entries + entries
fun valueOf(s: String): Language? = values().find { it.name == s } as Language?
}
}
Expand All @@ -64,7 +69,7 @@ fun cli(args: Array<String>) {
ArgType.Choice(
Language.values().map { it.name }.map { Language.valueOf(it) ?: error("Language not found") },
{ Language.valueOf(it) ?: error("Language not found") }), shortName = "l", description = "Language type"
).default(Language.Jvm.Kotlin).multiple()
).default(Jvm.Kotlin).multiple()
val openapi by parser.option(
ArgType.Choice<OpenapiVersion>(),
shortName = "a",
Expand Down Expand Up @@ -104,30 +109,42 @@ private fun compile(
}
.map { (results, file) -> write(results, file) }
} else {
if(input.endsWith(".ws")){
return WirespecFile(FullFilePath.parse(input))
.wirespec(languages,packageName,output,logger)

}
Directory(input)
.wirespecFiles()
.forEach { wsFile ->
val path = wsFile.path.out(packageName, output)
wsFile.read()
.let(WirespecSpec::compile)(logger)
.let { compiler ->
emit(languages, packageName, path, logger)
.map { (emitter, file) ->
val result = compiler(emitter)
if (!emitter.split) result.map { listOf(wsFile.path.fileName.replaceFirstChar(Char::uppercase) to it.first().second) } to file
else result to file
}
}
.map { (results, file) ->
when (results) {
is Either.Right -> write(results.value, file)
is Either.Left -> println(results.value)
}
}
}
.forEach { it.wirespec(languages,packageName,output,logger)}
}
}

private fun WirespecFile.wirespec(
languages: Set<Language>,
packageName: String,
output: String?,
logger: Logger
) {
val path = this.path.out(packageName, output)
read()
.let(WirespecSpec::compile)(logger)
.let { compiler ->
emit(languages, packageName, path, logger)
.map { (emitter, file) ->
val result = compiler(emitter)
if (!emitter.split) result.map { listOf(this.path.fileName.replaceFirstChar(Char::uppercase) to it.first().second) } to file
else result to file
}
}
.map { (results, file) ->
when (results) {
is Either.Right -> write(results.value, file)
is Either.Left -> println(results.value)
}
}
}

private fun emit(
languages: Set<Language>,
packageName: String,
Expand All @@ -142,6 +159,8 @@ private fun emit(
Scala -> ScalaEmitter(packageName, logger) to ScalaFile(path(Extension.Scala))
TypeScript -> TypeScriptEmitter(logger) to TypeScriptFile(path(Extension.TypeScript))
Wirespec -> WirespecEmitter(logger) to WirespecFile(path(Extension.Wirespec))
OpenApiV2 -> OpenApiV2Emitter(logger) to JsonFile(path(Extension.Json))
OpenApiV3 -> OpenApiV2Emitter(logger) to JsonFile(path(Extension.Json))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import community.flock.wirespec.compiler.cli.io.Extension.Wirespec
data class FullFilePath(val directory: String, val fileName: String, val extension: Extension = Wirespec) {
companion object {
fun parse(input: String): FullFilePath {
val list = input.split("/", ".")
val list = input.split("/").let { it.dropLast(1) + it.last().split(".") }
val extension = list.last().lowercase()
.let { ext -> Extension.entries.find { it.ext == ext } }
?: error("Invalid file extension")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package community.flock.wirespec.compiler.cli

import community.flock.wirespec.compiler.cli.io.Extension
import community.flock.wirespec.compiler.cli.io.FullFilePath
import community.flock.wirespec.compiler.cli.io.JavaFile
import community.flock.wirespec.compiler.cli.io.JsonFile
import community.flock.wirespec.compiler.cli.io.KotlinFile
import community.flock.wirespec.compiler.cli.io.TypeScriptFile
import community.flock.wirespec.compiler.cli.io.WirespecFile
import community.flock.wirespec.compiler.core.emit.common.DEFAULT_PACKAGE_NAME
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class CliTest {
Expand Down Expand Up @@ -143,6 +147,25 @@ class CliTest {
file shouldContain expected
}

@Test
fun testCliWirespecToOpenApi() {
val packageName = "community.flock.ws"
val packageDir = packageName.replace(".", "/")
val input = "${inputDir}/wirespec/todo.ws"
val output = outputDir()

cli(arrayOf(input, "-o", output, "-l", "OpenApiV2", "-p", packageDir))
cli(arrayOf("${output}/$packageDir/Todo.json", "-o", output, "-l", "Wirespec", "-p", packageDir, "-a", "v2"))

val pathWs = FullFilePath("$output/$packageDir", "Todo", Extension.Wirespec)
val fileWs = WirespecFile(pathWs).read()

val pathInput = FullFilePath("$inputDir/wirespec", "todo")
val fileInput = WirespecFile(pathInput).read()

assertEquals(fileInput, fileWs)
}

private fun getRandomString(length: Int) = (1..length)
.map { allowedChars.random() }
.joinToString("")
Expand Down
40 changes: 40 additions & 0 deletions src/compiler/cli/src/commonTest/resources/wirespec/todo.ws
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
endpoint GetTodos GET /todos ? {done: Boolean?} -> {
200 -> Todo[]
404 -> Error
}

endpoint CreateTodo POST TodoInput /todos -> {
200 -> Todo
404 -> Error
}

endpoint GetTodoById GET /todos/{id: String} -> {
200 -> Todo
404 -> Error
}

endpoint UpdateTodo PUT TodoInput /todos/{id: String} -> {
200 -> Todo
404 -> Error
}

endpoint DeleteTodo DELETE /todos/{id: String} -> {
200 -> Todo
404 -> Error
}

type Todo {
id: String,
name: String,
done: Boolean
}

type TodoInput {
name: String,
done: Boolean
}

type Error {
code: String,
description: String?
}
2 changes: 2 additions & 0 deletions src/compiler/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ kotlin {
commonMain {
dependencies {
api(ARROW_CORE)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("community.flock.kotlinx.openapi.bindings:kotlin-openapi-bindings:0.0.19")
}
}
commonTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package community.flock.wirespec.compiler.core.emit

import community.flock.wirespec.compiler.core.emit.common.DEFAULT_PACKAGE_NAME
import community.flock.wirespec.compiler.core.emit.common.Emitter
import community.flock.wirespec.compiler.core.emit.common.AbstractEmitter
import community.flock.wirespec.compiler.core.parse.AST
import community.flock.wirespec.compiler.core.parse.nodes.Endpoint
import community.flock.wirespec.compiler.core.parse.nodes.Enum
Expand All @@ -14,7 +14,7 @@ import community.flock.wirespec.compiler.utils.noLogger
class JavaEmitter(
packageName: String = DEFAULT_PACKAGE_NAME,
logger: Logger = noLogger
) : Emitter(logger, true) {
) : AbstractEmitter(logger, true) {

override val shared = """
|package community.flock.wirespec;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package community.flock.wirespec.compiler.core.emit

import community.flock.wirespec.compiler.core.emit.common.DEFAULT_PACKAGE_NAME
import community.flock.wirespec.compiler.core.emit.common.Emitter
import community.flock.wirespec.compiler.core.emit.common.Emitter.Companion.firstToUpper
import community.flock.wirespec.compiler.core.emit.common.Emitter.Companion.isInt
import community.flock.wirespec.compiler.core.emit.common.AbstractEmitter
import community.flock.wirespec.compiler.core.emit.common.AbstractEmitter.Companion.firstToUpper
import community.flock.wirespec.compiler.core.emit.common.AbstractEmitter.Companion.isInt
import community.flock.wirespec.compiler.core.parse.AST
import community.flock.wirespec.compiler.core.parse.nodes.Endpoint
import community.flock.wirespec.compiler.core.parse.nodes.Enum
Expand All @@ -16,7 +16,7 @@ import community.flock.wirespec.compiler.utils.noLogger
class KotlinEmitter(
private val packageName: String = DEFAULT_PACKAGE_NAME,
logger: Logger = noLogger
) : Emitter(logger) {
) : AbstractEmitter(logger) {

override val shared = """
|package community.flock.wirespec
Expand Down
Loading

0 comments on commit 427a003

Please sign in to comment.