initial cut of backend/web modules
This commit is contained in:
parent
072d39d101
commit
d94534a2b8
20 changed files with 196 additions and 38 deletions
1
backend/.gitignore
vendored
Normal file
1
backend/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
21
backend/build.gradle.kts
Normal file
21
backend/build.gradle.kts
Normal file
|
@ -0,0 +1,21 @@
|
|||
plugins {
|
||||
id("kotlin-platform-jvm")
|
||||
application
|
||||
kotlin("plugin.serialization")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}")
|
||||
|
||||
implementation("io.ktor:ktor-server-core:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-server-netty:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-serialization:${Versions.ktor}")
|
||||
|
||||
implementation("ch.qos.logback:logback-classic:1.2.3")
|
||||
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinxSerialization}") // JVM dependency
|
||||
implementation("io.ktor:ktor-websockets:${Versions.ktor}")
|
||||
|
||||
implementation(project(":common"))
|
||||
}
|
|
@ -1,23 +1,17 @@
|
|||
package com.surrus
|
||||
|
||||
import io.ktor.response.*
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.serialization.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import org.litote.kmongo.*
|
||||
import org.litote.kmongo.async.*
|
||||
import org.litote.kmongo.coroutine.*
|
||||
import org.litote.kmongo.async.getCollection
|
||||
import com.mongodb.ConnectionString
|
||||
import com.surrus.common.repository.PeopleInSpaceRepository
|
||||
import io.ktor.application.call
|
||||
import io.ktor.application.install
|
||||
import io.ktor.features.ContentNegotiation
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.content.resources
|
||||
import io.ktor.http.content.static
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.xml.bind.JAXBElement
|
||||
|
||||
|
||||
fun main() {
|
||||
val repository = PeopleInSpaceRepository()
|
||||
|
@ -28,8 +22,20 @@ fun main() {
|
|||
}
|
||||
|
||||
routing {
|
||||
|
||||
get("/") {
|
||||
call.respondText(
|
||||
this::class.java.classLoader.getResource("index.html")!!.readText(),
|
||||
ContentType.Text.Html
|
||||
)
|
||||
}
|
||||
|
||||
static("/") {
|
||||
resources("")
|
||||
}
|
||||
|
||||
get("/people") {
|
||||
repository.fetchPeopleAsFlow().collect {
|
||||
repository.fetchPeopleAsFlow()?.collect {
|
||||
call.respond(it)
|
||||
}
|
||||
}
|
11
backend/src/main/resources/index.html
Normal file
11
backend/src/main/resources/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>People In Space</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>People In Space</h1>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -19,10 +19,8 @@ allprojects {
|
|||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven("https://kotlin.bintray.com/kotlin-js-wrappers/")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("clean").configure {
|
||||
delete("build")
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ android {
|
|||
compileSdkVersion(29)
|
||||
buildToolsVersion("29.0.2")
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion(21)
|
||||
targetSdkVersion(29)
|
||||
|
@ -57,6 +56,11 @@ kotlin {
|
|||
homepage = "Link to a Kotlin/Native module homepage"
|
||||
}
|
||||
|
||||
js {
|
||||
browser {
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
|
@ -123,9 +127,6 @@ kotlin {
|
|||
|
||||
// Ktor
|
||||
implementation("io.ktor:ktor-server-core:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-server-netty:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-websockets:${Versions.ktor}")
|
||||
implementation("org.litote.kmongo:kmongo-coroutine-serialization:3.12.2")
|
||||
|
||||
implementation("io.ktor:ktor-client-core-jvm:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-client-json-jvm:${Versions.ktor}")
|
||||
|
@ -206,6 +207,27 @@ kotlin {
|
|||
implementation("com.squareup.sqldelight:runtime-macosx64:${Versions.sqlDelight}")
|
||||
}
|
||||
}
|
||||
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-js"))
|
||||
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Versions.kotlinCoroutines}")
|
||||
|
||||
// ktor
|
||||
implementation("io.ktor:ktor-client-js:${Versions.ktor}") //include http&websockets
|
||||
implementation("io.ktor:ktor-client-json-js:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-client-logging-js:${Versions.ktor}")
|
||||
implementation("io.ktor:ktor-client-serialization-js:${Versions.ktor}")
|
||||
|
||||
// Serialize
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinxSerialization}")
|
||||
|
||||
// SQL Delight
|
||||
//implementation("com.squareup.sqldelight:sqljs-driver:${Versions.sqlDelight}")
|
||||
implementation("com.squareup.sqldelight:runtime-js:${Versions.sqlDelight}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,3 +237,4 @@ sqldelight {
|
|||
sourceFolders = listOf("sqldelight")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import kotlinx.coroutines.launch
|
|||
|
||||
lateinit var appContext: Context
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase {
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
val driver = AndroidSqliteDriver(PeopleInSpaceDatabase.Schema, appContext, "peopleinspace.db")
|
||||
return PeopleInSpaceDatabase(driver)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.surrus.peopleinspace.db.PeopleInSpaceDatabase
|
|||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
|
||||
expect fun createDb() : PeopleInSpaceDatabase
|
||||
expect fun createDb() : PeopleInSpaceDatabase?
|
||||
|
||||
// TEMP until following is resolved https://github.com/ktorio/ktor/issues/1622
|
||||
expect fun ktorScope(block: suspend () -> Unit)
|
||||
|
@ -18,7 +18,7 @@ expect fun ktorScope(block: suspend () -> Unit)
|
|||
class PeopleInSpaceRepository {
|
||||
private val peopleInSpaceApi = PeopleInSpaceApi()
|
||||
private val peopleInSpaceDatabase = createDb()
|
||||
private val peopleInSpaceQueries = peopleInSpaceDatabase.peopleInSpaceQueries
|
||||
private val peopleInSpaceQueries = peopleInSpaceDatabase?.peopleInSpaceQueries
|
||||
|
||||
init {
|
||||
ktorScope {
|
||||
|
@ -26,25 +26,25 @@ class PeopleInSpaceRepository {
|
|||
}
|
||||
}
|
||||
|
||||
fun fetchPeopleAsFlow() = peopleInSpaceQueries.selectAll(mapper = { name, craft ->
|
||||
fun fetchPeopleAsFlow() = peopleInSpaceQueries?.selectAll(mapper = { name, craft ->
|
||||
Assignment(name = name, craft = craft)
|
||||
}).asFlow().mapToList()
|
||||
})?.asFlow()?.mapToList()
|
||||
|
||||
private suspend fun fetchAndStorePeople() {
|
||||
val result = peopleInSpaceApi.fetchPeople()
|
||||
|
||||
// this is very basic implementation for now that removes all existing rows
|
||||
// in db and then inserts reults from api request
|
||||
peopleInSpaceQueries.deleteAll()
|
||||
peopleInSpaceQueries?.deleteAll()
|
||||
result.people.forEach {
|
||||
peopleInSpaceQueries.insertItem(it.name, it.craft)
|
||||
peopleInSpaceQueries?.insertItem(it.name, it.craft)
|
||||
}
|
||||
}
|
||||
|
||||
// called from iOS/watchOS/macOS client
|
||||
fun fetchPeople(success: (List<Assignment>) -> Unit) {
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
fetchPeopleAsFlow().collect {
|
||||
fetchPeopleAsFlow()?.collect {
|
||||
success(it)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase {
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
val driver = NativeSqliteDriver(PeopleInSpaceDatabase.Schema, "peopleinspace.db")
|
||||
return PeopleInSpaceDatabase(driver)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.surrus.common.repository
|
||||
|
||||
import com.surrus.peopleinspace.db.PeopleInSpaceDatabase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
return null
|
||||
}
|
||||
|
||||
actual fun ktorScope(block: suspend () -> Unit) {
|
||||
GlobalScope.launch(Dispatchers.Main) { block() }
|
||||
}
|
|
@ -7,12 +7,14 @@ import kotlinx.coroutines.flow.collect
|
|||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
@InternalCoroutinesApi
|
||||
fun main() = runBlocking {
|
||||
fun main() {
|
||||
runBlocking {
|
||||
val api = PeopleInSpaceApi()
|
||||
println(api.fetchPeople())
|
||||
|
||||
val repository = PeopleInSpaceRepository()
|
||||
repository.fetchPeopleAsFlow().collect {
|
||||
repository.fetchPeopleAsFlow()?.collect {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
|
|||
import com.surrus.peopleinspace.db.PeopleInSpaceDatabase
|
||||
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase {
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
|
||||
.also { PeopleInSpaceDatabase.Schema.create(it) }
|
||||
return PeopleInSpaceDatabase(driver)
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.surrus.common.repository
|
|||
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
|
||||
import com.surrus.peopleinspace.db.PeopleInSpaceDatabase
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase {
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
val driver = NativeSqliteDriver(PeopleInSpaceDatabase.Schema, "peopleinspace.db")
|
||||
return PeopleInSpaceDatabase(driver)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
actual fun createDb(): PeopleInSpaceDatabase {
|
||||
actual fun createDb(): PeopleInSpaceDatabase? {
|
||||
val driver = NativeSqliteDriver(PeopleInSpaceDatabase.Schema, "peopleinspace.db")
|
||||
return PeopleInSpaceDatabase(driver)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include(":web")
|
||||
include(":backend")
|
||||
rootProject.name = "PeopleInSpace"
|
||||
|
||||
enableFeaturePreview("GRADLE_METADATA")
|
||||
|
|
1
web/.gitignore
vendored
Normal file
1
web/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
29
web/build.gradle.kts
Normal file
29
web/build.gradle.kts
Normal file
|
@ -0,0 +1,29 @@
|
|||
plugins {
|
||||
kotlin("js")
|
||||
kotlin("plugin.serialization")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-js"))
|
||||
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.3.5")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-html-js:0.7.1")
|
||||
implementation(npm("text-encoding"))
|
||||
implementation(npm("abort-controller"))
|
||||
implementation(npm("bufferutil"))
|
||||
implementation(npm("utf-8-validate"))
|
||||
implementation(npm("fs"))
|
||||
|
||||
//React, React DOM + Wrappers (chapter 3)
|
||||
implementation("org.jetbrains:kotlin-react:16.13.0-pre.93-kotlin-1.3.70")
|
||||
implementation("org.jetbrains:kotlin-react-dom:16.13.0-pre.93-kotlin-1.3.70")
|
||||
implementation(npm("react", "16.13.0"))
|
||||
implementation(npm("react-dom", "16.13.0"))
|
||||
|
||||
|
||||
implementation(project(":common"))
|
||||
}
|
||||
|
||||
|
||||
kotlin.target.browser { }
|
||||
|
29
web/src/main/kotlin/App.kt
Normal file
29
web/src/main/kotlin/App.kt
Normal file
|
@ -0,0 +1,29 @@
|
|||
import com.surrus.common.remote.Assignment
|
||||
import com.surrus.common.remote.PeopleInSpaceApi
|
||||
import react.*
|
||||
import react.dom.*
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
val scope = MainScope()
|
||||
val api = PeopleInSpaceApi()
|
||||
|
||||
val App = functionalComponent<RProps> { _ ->
|
||||
val (people, setPeople) = useState(emptyList<Assignment>())
|
||||
|
||||
useEffect(dependencies = listOf()) {
|
||||
scope.launch {
|
||||
setPeople(api.fetchPeople().people)
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
+"People In Space"
|
||||
}
|
||||
ul {
|
||||
people.forEach { item ->
|
||||
li {
|
||||
+"${item.name} (${item.craft})"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
web/src/main/kotlin/Main.kt
Normal file
9
web/src/main/kotlin/Main.kt
Normal file
|
@ -0,0 +1,9 @@
|
|||
import react.child
|
||||
import react.dom.render
|
||||
import kotlin.browser.document
|
||||
|
||||
fun main() {
|
||||
render(document.getElementById("root")) {
|
||||
child(functionalComponent = App)
|
||||
}
|
||||
}
|
11
web/src/main/resources/index.html
Normal file
11
web/src/main/resources/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>People In Space</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="web.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue