Skip to content

Commit

Permalink
feat: add query params and headers to wirespec language (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
jerrevanveluw authored Nov 17, 2023
1 parent 3ef1c12 commit d4e4ef3
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 76 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ mac:
linux:
$(shell pwd)/scripts/linux.sh

jvm:
$(shell pwd)/scripts/jvm.sh

example:
$(shell pwd)/scripts/example.sh

Expand Down
7 changes: 1 addition & 6 deletions scripts/image.sh
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
#!/usr/bin/env bash

buildNothing=false
archSpecific=""

if [[ $(uname -m) = arm64 ]]; then
archSpecific="--platform=linux/amd64"
fi

if [[ $WIRESPEC_BUILD_MAC != true ]]; then
buildNothing=true
fi

if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_LINUX = true || $buildNothing = true ]]; then
if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_LINUX = true ]]; then
docker build $archSpecific -t wirespec .
fi
10 changes: 10 additions & 0 deletions scripts/jvm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

export WIRESPEC_BUILD_JVM=true

dir="$(dirname -- "$0")"

"$dir"/build.sh &&
"$dir"/image.sh &&
"$dir"/test.sh &&
"$dir"/example.sh
14 changes: 8 additions & 6 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if [[ $(uname -m) = arm64 ]]; then
archSpecific="--platform=linux/amd64"
fi

if [[ $WIRESPEC_BUILD_MAC != true ]]; then
if [[ $WIRESPEC_BUILD_JVM != true ]]; then
buildNothing=true
fi

Expand All @@ -22,15 +22,17 @@ if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_MAC = true ]]; then
./src/compiler/$artifactName/build/bin/$macosArch/releaseExecutable/$artifactName.kexe -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.openapi.generated" -a v2 "$(pwd)"/types/petstore.json
fi

if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_LINUX = true || $buildNothing = true ]]; then
if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_LINUX = true ]]; then
echo "Test docker image"
docker run $archSpecific --rm -it -v "$(pwd)"/types:/app/types wirespec
fi

if [[ $WIRESPEC_BUILD_ALL = true || $WIRESPEC_BUILD_JVM = true || $buildNothing = true ]]; then
echo "Test JVM artifact"
java -jar src/compiler/$artifactName/build/libs/$artifactName-$version-all.jar -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.wirespec.generated" "$(pwd)"/types
java -jar src/compiler/$artifactName/build/libs/$artifactName-$version-all.jar -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.openapi.generated" -a v2 "$(pwd)"/types/petstore.json
fi

echo "Test Node.js artifact"
node build/js/packages/wirespec-src-compiler-$artifactName/kotlin/wirespec-src-compiler-$artifactName.js -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.wirespec.generated" "$(pwd)"/types
node build/js/packages/wirespec-src-compiler-$artifactName/kotlin/wirespec-src-compiler-$artifactName.js -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.openapi.generated" -a v2 "$(pwd)"/types/petstore.json

echo "Test JVM artifact"
java -jar src/compiler/$artifactName/build/libs/$artifactName-$version-all.jar -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.wirespec.generated" "$(pwd)"/types
java -jar src/compiler/$artifactName/build/libs/$artifactName-$version-all.jar -l Java -l Kotlin -l Scala -l TypeScript -l Wirespec -p "community.flock.openapi.generated" -a v2 "$(pwd)"/types/petstore.json
14 changes: 9 additions & 5 deletions src/compiler/cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ kotlin {
val buildAll = "WIRESPEC_BUILD_ALL".fromEnv()
val buildMacX86 = buildAll || "WIRESPEC_BUILD_MAC_X86".fromEnv()
val buildMacArm = buildAll || "WIRESPEC_BUILD_MAC_ARM".fromEnv()
val buildNothing = !buildMacX86 && !buildMacArm
val buildLinux = buildAll || "WIRESPEC_BUILD_LINUX".fromEnv() || buildNothing
val buildLinux = buildAll || "WIRESPEC_BUILD_LINUX".fromEnv()
val buildNothing = !buildMacX86 && !buildMacArm && !buildLinux
val buildJvm = buildAll || "WIRESPEC_BUILD_JVM".fromEnv() || buildNothing

if (buildMacX86) macosX64 { build() }
if (buildMacArm) macosArm64 { build() }
Expand Down Expand Up @@ -84,12 +85,15 @@ kotlin {
dependsOn(desktopMain)
}
}
val jsMain by getting {
dependsOn(commonMain)
if (buildJvm) {
val jvmMain by getting {
dependsOn(commonMain)
}
}
val jvmMain by getting {
val jsMain by getting {
dependsOn(commonMain)
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import community.flock.wirespec.compiler.core.tokenize.types.CustomRegex
import community.flock.wirespec.compiler.core.tokenize.types.CustomType
import community.flock.wirespec.compiler.core.tokenize.types.CustomValue
import community.flock.wirespec.compiler.core.tokenize.types.ForwardSlash
import community.flock.wirespec.compiler.core.tokenize.types.Hash
import community.flock.wirespec.compiler.core.tokenize.types.Invalid
import community.flock.wirespec.compiler.core.tokenize.types.LeftCurly
import community.flock.wirespec.compiler.core.tokenize.types.Method
Expand Down Expand Up @@ -45,6 +46,7 @@ object Wirespec : LanguageSpec {
Regex("^:") to Colon,
Regex("^,") to Comma,
Regex("^\\?") to QuestionMark,
Regex("^#") to Hash,
Regex("^\\[\\]") to Brackets,
Regex("^String") to WsString,
Regex("^Integer") to WsInteger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import community.flock.wirespec.compiler.core.tokenize.types.Colon
import community.flock.wirespec.compiler.core.tokenize.types.CustomType
import community.flock.wirespec.compiler.core.tokenize.types.CustomValue
import community.flock.wirespec.compiler.core.tokenize.types.ForwardSlash
import community.flock.wirespec.compiler.core.tokenize.types.Hash
import community.flock.wirespec.compiler.core.tokenize.types.LeftCurly
import community.flock.wirespec.compiler.core.tokenize.types.Method
import community.flock.wirespec.compiler.core.tokenize.types.Path
import community.flock.wirespec.compiler.core.tokenize.types.QuestionMark
import community.flock.wirespec.compiler.core.tokenize.types.RightCurly
import community.flock.wirespec.compiler.core.tokenize.types.StatusCode
import community.flock.wirespec.compiler.core.tokenize.types.WirespecType
Expand All @@ -28,6 +30,8 @@ import community.flock.wirespec.compiler.utils.Logger

class EndpointParser(logger: Logger) : AbstractParser(logger) {

private val typeParser = TypeParser(logger)

fun TokenProvider.parseEndpoint(): Either<WirespecException, Endpoint> = either {
eatToken().bind()
token.log()
Expand Down Expand Up @@ -61,10 +65,39 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
}

val segments = mutableListOf<Endpoint.Segment>().apply {
while (token.type !is Arrow) {
while (token.type !is QuestionMark && token.type !is Hash && token.type !is Arrow) {
add(parseEndpointSegments().bind())
}
}.also { eatToken().bind() }
}

val queryParams = when (token.type) {
is QuestionMark -> {
eatToken().bind()
when (token.type) {
is LeftCurly -> with(typeParser) { parseTypeShape().bind() }.value
else -> raise(WrongTokenException<LeftCurly>(token))
}
}

else -> emptyList()
}

val headers = when (token.type) {
is Hash -> {
eatToken().bind()
when (token.type) {
is LeftCurly -> with(typeParser) { parseTypeShape().bind() }.value
else -> raise(WrongTokenException<LeftCurly>(token))
}
}

else -> emptyList()
}

when (token.type) {
is Arrow -> eatToken().bind()
else -> raise(WrongTokenException<Arrow>(token))
}

when (token.type) {
is LeftCurly -> Unit
Expand All @@ -77,8 +110,8 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
name = name,
method = method,
path = segments,
query = emptyList(),
headers = emptyList(),
query = queryParams,
headers = headers,
cookies = emptyList(),
requests = requests,
responses = responses,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,7 @@ class TypeParser(logger: Logger) : AbstractParser(logger) {
}
}

private fun TokenProvider.parseTypeDefinition(typeName: String) = either {
eatToken().bind()
token.log()
when (token.type) {
is LeftCurly -> Type(typeName, parseTypeShape().bind())
else -> raise(WrongTokenException<LeftCurly>(token).also { eatToken().bind() })
}.also {
when (token.type) {
is RightCurly -> eatToken().bind()
else -> raise(WrongTokenException<RightCurly>(token).also { eatToken().bind() })
}
}
}

private fun TokenProvider.parseTypeShape() = either {
fun TokenProvider.parseTypeShape(): Either<WirespecException, Type.Shape> = either {
eatToken().bind()
token.log()
when (token.type) {
Expand All @@ -61,9 +47,23 @@ class TypeParser(logger: Logger) : AbstractParser(logger) {
}

else -> raise(WrongTokenException<CustomValue>(token).also { eatToken().bind() })
}.also {
when (token.type) {
is RightCurly -> eatToken().bind()
else -> raise(WrongTokenException<RightCurly>(token).also { eatToken().bind() })
}
}.let(Type::Shape)
}

private fun TokenProvider.parseTypeDefinition(typeName: String) = either {
eatToken().bind()
token.log()
when (token.type) {
is LeftCurly -> Type(typeName, parseTypeShape().bind())
else -> raise(WrongTokenException<LeftCurly>(token).also { eatToken().bind() })
}
}

private fun TokenProvider.parseField(identifier: Type.Shape.Field.Identifier) = either {
eatToken().bind()
token.log()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ data object RightCurly : TokenType
data object Colon : TokenType
data object Comma : TokenType
data object QuestionMark : TokenType
data object Hash : TokenType
data object ForwardSlash : TokenType
data object Brackets : TokenType
data object CustomValue : TokenType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import community.flock.wirespec.compiler.core.parse.nodes.Endpoint.Method.POST
import community.flock.wirespec.compiler.core.parse.nodes.Endpoint.Segment.Literal
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Identifier
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Reference
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Reference.Primitive
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Reference.Primitive.Type.String
import community.flock.wirespec.compiler.core.tokenize.tokenize
import community.flock.wirespec.compiler.utils.noLogger
import io.kotest.assertions.arrow.core.shouldBeRight
Expand All @@ -22,7 +24,7 @@ class ParseEndpointTest {
private fun parser() = Parser(noLogger)

@Test
fun testEndpointParserWithCorrectInput() {
fun testEndpointParser() {
val source = """
endpoint GetTodos GET /todos -> {
200 -> Todo[]
Expand All @@ -45,7 +47,7 @@ class ParseEndpointTest {
}

@Test
fun testPathParamsParserWithCorrectInput() {
fun testPathParamsParser() {
val source = """
endpoint PostTodo POST Todo /todos -> {
200 -> Todo
Expand Down Expand Up @@ -75,7 +77,7 @@ class ParseEndpointTest {
}

@Test
fun testRequestBodyParserWithCorrectInput() {
fun testRequestBodyParser() {
val source = """
endpoint GetTodo GET /todos/{id: String} -> {
200 -> Todo
Expand All @@ -95,8 +97,8 @@ class ParseEndpointTest {
path shouldBe listOf(
Literal("todos"), Endpoint.Segment.Param(
identifier = Identifier("id"),
reference = Reference.Primitive(
type = Reference.Primitive.Type.String,
reference = Primitive(
type = String,
isIterable = false,
isMap = false,
)
Expand All @@ -105,4 +107,68 @@ class ParseEndpointTest {
requests.shouldBeEmpty()
}
}

@Test
fun testQueryParamsParser() {
val source = """
endpoint GetTodos GET /todos?{name: String, date: String} -> {
200 -> Todo[]
}
""".trimIndent()

Wirespec.tokenize(source)
.let(parser()::parse)
.shouldBeRight()
.also { it.size shouldBe 1 }
.first()
.shouldBeInstanceOf<Endpoint>()
.query.shouldNotBeEmpty().also { it.size shouldBe 2 }.take(2).let {
val (one, two) = it
one.run {
identifier.value shouldBe "name"
reference.shouldBeInstanceOf<Primitive>().type shouldBe String
isNullable shouldBe false
}
two.run {
identifier.value shouldBe "date"
reference.shouldBeInstanceOf<Primitive>().type shouldBe String
isNullable shouldBe false
}
}


}

@Test
fun testHeadersParser() {
val source = """
endpoint GetTodos GET /todos#{name: String, date: String} -> {
200 -> Todo[]
}
""".trimIndent()

Wirespec.tokenize(source)
.let(parser()::parse)
.shouldBeRight()
.also { it.size shouldBe 1 }
.first()
.shouldBeInstanceOf<Endpoint>()
.headers.shouldNotBeEmpty().also { it.size shouldBe 2 }.take(2).let {
val (one, two) = it
one.run {
identifier.value shouldBe "name"
reference.shouldBeInstanceOf<Primitive>().type shouldBe String
isNullable shouldBe false
}
two.run {
identifier.value shouldBe "date"
reference.shouldBeInstanceOf<Primitive>().type shouldBe String
isNullable shouldBe false
}
}


}
}
Loading

0 comments on commit d4e4ef3

Please sign in to comment.