6 Create minimal Server-API for client tests - basics
This commit is contained in:
1 parent
5ce25ff422
commit
b8f924b578
17 files changed
+102
-32
No files matched your search
@@ -1,3 +1,3 @@
|
|||||||
#auto generated
|
#auto generated
|
||||||
#Sun Feb 08 23:42:46 CET 2026
|
#Mon Feb 09 23:38:51 CET 2026
|
||||||
build.number=224
|
build.number=226
|
||||||
@@ -23,7 +23,6 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.keinekekse.app.books.generated.resources.Res
|
import net.keinekekse.app.books.generated.resources.Res
|
||||||
import net.keinekekse.app.books.generated.resources.compose_multiplatform
|
import net.keinekekse.app.books.generated.resources.compose_multiplatform
|
||||||
import net.keinekekse.app.books.ui.theme.AppTheme
|
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
@@ -33,13 +32,13 @@ private val logger = KotlinLogging.logger {}
|
|||||||
@Composable
|
@Composable
|
||||||
@Preview
|
@Preview
|
||||||
fun App() {
|
fun App() {
|
||||||
/*MaterialTheme*/
|
MaterialTheme {
|
||||||
/*
|
/*
|
||||||
eigenes Theme -> https://material-foundation.github.io/material-theme-builder/
|
eigenes Theme -> https://material-foundation.github.io/material-theme-builder/
|
||||||
den Download in den source code übernehmen (in Theme.kt sind Anpassungen nötig)
|
den Download in den source code übernehmen (in Theme.kt sind Anpassungen nötig)
|
||||||
per default hat die generierte Klasse den Namen AppTheme.
|
per default hat die generierte Klasse den Namen AppTheme.
|
||||||
|
// AppTheme {
|
||||||
*/
|
*/
|
||||||
AppTheme {
|
|
||||||
val test = koinInject<TestAuth>()
|
val test = koinInject<TestAuth>()
|
||||||
var showContent by remember { mutableStateOf(false) }
|
var showContent by remember { mutableStateOf(false) }
|
||||||
Column(
|
Column(
|
||||||
@@ -81,8 +80,12 @@ class TestAuth(val httpClient: HttpClient) {
|
|||||||
private val srv = "https://kas.keinekekse.net/"
|
private val srv = "https://kas.keinekekse.net/"
|
||||||
suspend fun request(url: String) {
|
suspend fun request(url: String) {
|
||||||
logger.debug { "connecting" }
|
logger.debug { "connecting" }
|
||||||
val response = httpClient.get(srv + url)
|
// val response = httpClient.get(srv + "testdb/books")
|
||||||
|
// val books: List<Book> = response.body()
|
||||||
|
|
||||||
|
val response = httpClient.get(srv + url + "testdb/books")
|
||||||
val body = response.bodyAsText()
|
val body = response.bodyAsText()
|
||||||
|
|
||||||
logger.debug { "call to $url" }
|
logger.debug { "call to $url" }
|
||||||
logger.debug { response.status }
|
logger.debug { response.status }
|
||||||
logger.debug { body }
|
logger.debug { body }
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import net.keinekekse.version.Version
|
|||||||
|
|
||||||
object VERSION: Version {
|
object VERSION: Version {
|
||||||
override val version = "1.0.0"
|
override val version = "1.0.0"
|
||||||
override val fullVersion = "1.0.0+build.224"
|
override val fullVersion = "1.0.0+build.226"
|
||||||
override val major = 1
|
override val major = 1
|
||||||
override val minor = 0
|
override val minor = 0
|
||||||
override val patch = 0
|
override val patch = 0
|
||||||
override val preRelease = ""
|
override val preRelease = ""
|
||||||
override val buildMetadata = "build.224"
|
override val buildMetadata = "build.226"
|
||||||
override val buildDate = "2026-02-08T22:42:46.561391Z"
|
override val buildDate = "2026-02-09T22:38:51.084372Z"
|
||||||
override val displayName = "Books App"
|
override val displayName = "Books App"
|
||||||
override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
||||||
override val name = "books"
|
override val name = "books"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#auto generated
|
#auto generated
|
||||||
#Sun Feb 08 23:42:57 CET 2026
|
#Tue Feb 10 00:04:01 CET 2026
|
||||||
build.number=43
|
build.number=50
|
||||||
@@ -3,10 +3,7 @@ package net.keinekekse.app
|
|||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import net.keinekekse.app.server.VERSION
|
import net.keinekekse.app.server.VERSION
|
||||||
import net.keinekekse.app.server.config.configureDatabase
|
import net.keinekekse.app.server.config.*
|
||||||
import net.keinekekse.app.server.config.configureKoin
|
|
||||||
import net.keinekekse.app.server.config.configureRouting
|
|
||||||
import net.keinekekse.app.server.config.configureSecurity
|
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
@@ -22,13 +19,22 @@ fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
fun Application.module() {
|
fun Application.module() {
|
||||||
logger.info { "\n**\n** Starting ${VERSION.displayName} - ${VERSION.description} ${VERSION.fullVersion}\n**" }
|
logger.info {
|
||||||
|
"""
|
||||||
|
|
||||||
|
**
|
||||||
|
** Starting ${VERSION.displayName} - ${VERSION.description} ${VERSION.fullVersion}
|
||||||
|
**
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
configureSerialization()
|
||||||
configureKoin()
|
configureKoin()
|
||||||
configureSecurity()
|
configureSecurity()
|
||||||
configureRouting()
|
|
||||||
configureDatabase()
|
configureDatabase()
|
||||||
|
|
||||||
|
configureRouting()
|
||||||
|
|
||||||
/* // DB-Test
|
/* // DB-Test
|
||||||
transaction {
|
transaction {
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package net.keinekekse.app.server
|
|||||||
import net.keinekekse.version.Version
|
import net.keinekekse.version.Version
|
||||||
|
|
||||||
object VERSION: Version {
|
object VERSION: Version {
|
||||||
override val version = "0.1.0-beta.1+build.43"
|
override val version = "0.1.0-beta.1+build.50"
|
||||||
override val fullVersion = "0.1.0-beta.1+build.43"
|
override val fullVersion = "0.1.0-beta.1+build.50"
|
||||||
override val major = 0
|
override val major = 0
|
||||||
override val minor = 1
|
override val minor = 1
|
||||||
override val patch = 0
|
override val patch = 0
|
||||||
override val preRelease = "beta.1"
|
override val preRelease = "beta.1"
|
||||||
override val buildMetadata = "build.43"
|
override val buildMetadata = "build.50"
|
||||||
override val buildDate = "2026-02-08T22:42:57.727025Z"
|
override val buildDate = "2026-02-09T23:04:01.715682Z"
|
||||||
override val displayName = "kAS"
|
override val displayName = "kAS"
|
||||||
override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
override val copyright = "Copyright (c) 2026 Hartmut Bauer"
|
||||||
override val name = "server"
|
override val name = "server"
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package net.keinekekse.app.server.config
|
|||||||
|
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import net.keinekekse.app.server.di.KoinApp
|
import net.keinekekse.app.server.di.KoinApp
|
||||||
import org.koin.dsl.koinConfiguration
|
import org.koin.ktor.plugin.Koin
|
||||||
import org.koin.logger.slf4jLogger
|
import org.koin.logger.slf4jLogger
|
||||||
import org.koin.plugin.module.dsl.withConfiguration
|
import org.koin.plugin.module.dsl.withConfiguration
|
||||||
|
|
||||||
fun Application.configureKoin() {
|
fun Application.configureKoin() {
|
||||||
koinConfiguration {
|
install(Koin) {
|
||||||
slf4jLogger()
|
slf4jLogger()
|
||||||
withConfiguration<KoinApp>()
|
withConfiguration<KoinApp>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import io.ktor.server.auth.*
|
|||||||
import io.ktor.server.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
import net.keinekekse.app.server.VERSION
|
import net.keinekekse.app.server.VERSION
|
||||||
|
import net.keinekekse.app.server.testdb.testDbRoute
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
@@ -22,5 +23,7 @@ fun Application.configureRouting() {
|
|||||||
call.respondText("Ktor ${VERSION.displayName} ${VERSION.fullVersion} - principal=${principal?.name}")
|
call.respondText("Ktor ${VERSION.displayName} ${VERSION.fullVersion} - principal=${principal?.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testDbRoute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package net.keinekekse.app.server.config
|
||||||
|
|
||||||
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
|
|
||||||
|
fun Application.configureSerialization() {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json(
|
||||||
|
json = kotlinx.serialization.json.Json {
|
||||||
|
prettyPrint = true
|
||||||
|
// isLenient = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.keinekekse.app.server.testdb.db
|
package net.keinekekse.app.server.testdb.db
|
||||||
|
|
||||||
import net.keinekekse.app.server.testdb.model.*
|
import net.keinekekse.app.book.model.*
|
||||||
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
import org.jetbrains.exposed.v1.core.dao.id.EntityID
|
||||||
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
|
||||||
import org.jetbrains.exposed.v1.dao.IntEntity
|
import org.jetbrains.exposed.v1.dao.IntEntity
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.server.testdb.model
|
||||||
|
|
||||||
|
import net.keinekekse.app.book.model.Artist
|
||||||
|
import net.keinekekse.app.book.model.Book
|
||||||
|
import net.keinekekse.app.book.model.Series
|
||||||
|
|
||||||
interface BookRepository {
|
interface BookRepository {
|
||||||
suspend fun allBooks(): List<Book>
|
suspend fun allBooks(): List<Book>
|
||||||
suspend fun bookById(id: Int): Book?
|
suspend fun bookById(id: Int): Book?
|
||||||
|
|||||||
+13
-4
@@ -1,12 +1,21 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.server.testdb.model
|
||||||
|
|
||||||
|
import net.keinekekse.app.book.model.Artist
|
||||||
|
import net.keinekekse.app.book.model.Book
|
||||||
|
import net.keinekekse.app.book.model.Series
|
||||||
|
import net.keinekekse.app.server.testdb.db.BookDAO
|
||||||
|
import net.keinekekse.app.server.testdb.db.daoToModel
|
||||||
|
import org.jetbrains.exposed.v1.jdbc.transactions.suspendTransaction
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
@Single
|
||||||
class BookRepositoryImpl : BookRepository {
|
class BookRepositoryImpl : BookRepository {
|
||||||
override suspend fun allBooks(): List<Book> {
|
override suspend fun allBooks(): List<Book> = suspendTransaction {
|
||||||
TODO("Not yet implemented")
|
BookDAO.all().map(::daoToModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun bookById(id: Int): Book? {
|
override suspend fun bookById(id: Int): Book? = suspendTransaction {
|
||||||
TODO("Not yet implemented")
|
BookDAO.findById(id)?.let { daoToModel(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun booksBySeries(series: Series): List<Book> {
|
override suspend fun booksBySeries(series: Series): List<Book> {
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package net.keinekekse.app.server.testdb
|
||||||
|
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import net.keinekekse.app.server.testdb.model.BookRepository
|
||||||
|
import org.koin.ktor.ext.inject
|
||||||
|
|
||||||
|
fun Route.testDbRoute() {
|
||||||
|
val repository: BookRepository by inject<BookRepository>()
|
||||||
|
|
||||||
|
// authenticate("auth-KC") {
|
||||||
|
route("/testdb") {
|
||||||
|
get("/books") {
|
||||||
|
// call.respondText("Test DB route")
|
||||||
|
val books = repository.allBooks()
|
||||||
|
call.respond(books)
|
||||||
|
}
|
||||||
|
get("/book/{id}") {
|
||||||
|
// TODO safe toInt conv
|
||||||
|
val id = call.parameters["id"]!!.toInt()
|
||||||
|
repository.bookById(id)?.let { call.respond(it) }
|
||||||
|
?: call.respondText("Book with id $id not found", status = HttpStatusCode.NotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.book.model
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.book.model
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.book.model
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package net.keinekekse.app.server.testdb.model
|
package net.keinekekse.app.book.model
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
Reference in new issue
Block a user