From 121a7575120fb99c6eb8e45f875d808d901ce4a1 Mon Sep 17 00:00:00 2001 From: Francisco Engenheiro Date: Sun, 17 Mar 2024 00:20:07 +0000 Subject: [PATCH] Refactors Ktor example to include more frontend targets --- README.md | 113 ++++++++++++------ convention-plugins/build.gradle.kts | 6 +- .../main/kotlin/root.publication.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kmp/build.gradle.kts | 25 ++++ .../androidMain/kotlin/models/Book.android.kt | 4 + .../kotlin/{ => target}/Platform.android.kt | 0 .../kotlin/AndroidPlatformTest.kt | 14 --- kmp/src/commonMain/kotlin/models/Book.kt | 2 +- kotlin-js-store/yarn.lock | 42 ------- ktor/build.gradle.kts | 99 ++++++++++----- .../.gitignore | 0 .../kotlin/Main.kt | 0 .../kotlin/application/ChatApplication.kt | 0 .../kotlin/application/ChatServer.kt | 0 .../application/WebSocketServerHandler.kt | 0 .../kotlin/application/models/ChatSession.kt | 0 .../kotlin/plugins/Headers.kt | 0 .../kotlin/plugins/Interceptors.kt | 0 .../kotlin/plugins/Monitoring.kt | 1 + .../kotlin/plugins/Sessions.kt | 0 .../kotlin/plugins/StatusPages.kt | 0 .../kotlin/plugins/WebSockets.kt | 0 .../kotlin/router/Routing.kt | 0 .../resources/application.conf | 0 .../resources/logback.xml | 0 .../resources/web/index.html | 0 .../kotlin/ChatApplicationTest.kt | 0 .../kotlin/Main.kt | 3 + .../kotlin/connection}/Connection.kt | 4 +- .../kotlin/connection}/WsClient.kt | 2 + .../kotlin/dom}/ChatDOMHandler.kt | 3 + 32 files changed, 192 insertions(+), 130 deletions(-) create mode 100644 kmp/src/androidMain/kotlin/models/Book.android.kt rename kmp/src/androidMain/kotlin/{ => target}/Platform.android.kt (100%) delete mode 100644 kmp/src/androidUnitTest/kotlin/AndroidPlatformTest.kt rename ktor/src/{backendMain => backendJvmMain}/.gitignore (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/Main.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/application/ChatApplication.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/application/ChatServer.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/application/WebSocketServerHandler.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/application/models/ChatSession.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/Headers.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/Interceptors.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/Monitoring.kt (99%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/Sessions.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/StatusPages.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/plugins/WebSockets.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/kotlin/router/Routing.kt (100%) rename ktor/src/{backendMain => backendJvmMain}/resources/application.conf (100%) rename ktor/src/{backendMain => backendJvmMain}/resources/logback.xml (100%) rename ktor/src/{backendMain => backendJvmMain}/resources/web/index.html (100%) rename ktor/src/{backendTest => backendJvmTest}/kotlin/ChatApplicationTest.kt (100%) rename ktor/src/{frontendMain => frontendJsMain}/kotlin/Main.kt (80%) rename ktor/src/{frontendMain/kotlin => frontendJsMain/kotlin/connection}/Connection.kt (93%) rename ktor/src/{frontendMain/kotlin => frontendJsMain/kotlin/connection}/WsClient.kt (97%) rename ktor/src/{frontendMain/kotlin => frontendJsMain/kotlin/dom}/ChatDOMHandler.kt (97%) diff --git a/README.md b/README.md index 7623455..600d9e3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,35 @@ # Experiments -## KMP - Kotlin Multiplatform +## Table of Contents + +- [Kotlin Multiplatform](#kotlin-multiplatform) + - [Architecture Overview](#architecture-overview) + - [Testing the Application](#testing-the-application) + - [Intermediate Source Sets](#intermediate-source-sets) + - [Adapter](#adapter) + - [Relevant Design Choices](#relevant-design-choices) +- [Kotlin-Js Interop](#kotlin-js-interop) + - [Javascript to Kotlin](#javascript-to-kotlin) + - [Demonstrations](#demonstrations) + - [NPM Dependencies](#npm-dependencies) + - [Build and Run](#build-and-run) + - [Kotlin to Javascript](#kotlin-to-javascript) + - [Demonstration](#demonstration) + - [Run](#run) + - [References](#references) +- [Ktor Framework](#ktor-framework) + - [Server](#server) + - [Launching the Application](#launching-the-application) + - [Define Application Module](#define-application-module) + - [Installing Plugins](#installing-plugins) + - [Defining Routes](#defining-routes) + - [Testing the Application](#testing-the-application-1) + - [Client](#client) + - [Requests](#requests) + - [Responses](#responses) + - [Demonstration](#demonstration-1) + +## Kotlin Multiplatform > The [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html) (KMP) technology facilitates the sharing of > application code across several platforms, @@ -24,10 +53,10 @@ following situations: 1. A certain functionality cannot be implemented commonly because: - - It requires access to specific target APIs; - - The libraries available for common code _(i.e., Standard Kotlin Library, Kotlinx)_ do not cover the desired - functionalities, - and there's no external KMP-compatible library available to be used as a dependency (or it is discouraged to use); + - It requires access to specific target APIs; + - The libraries available for common code _(i.e., Standard Kotlin Library, Kotlinx)_ do not cover the desired + functionalities, + and there's no external KMP-compatible library available to be used as a dependency (or it is discouraged to use); 2. A certain target does not directly support KMP _(e.g., Node.js)_, and thus an [adapter](#adapter) is needed for the code to be callable from the target. @@ -48,9 +77,9 @@ actual fun platformName(): String = "JVM" actual fun platformName(): String = "JS" ``` -| ![KMP Architecture](./docs/imgs/kmp-architecture.png) | -|:-----------------------------------------------------:| -| KMP Architecture Overview | +| KMP Architecture | +|:-------------------------------------------------------------------------------:| +| KMP Architecture Overview | ### Testing the Application @@ -60,12 +89,14 @@ and replaced by a few examples to practice the `expect/actual` mechanism more th This [addition](./kmp/src/commonMain/kotlin) follows the same principles: -- test common functionality in [CommonTest](./kmp/src/commonTest/kotlin); -- test platform-specific functionality in each platform's test source set (`Test`) +- **test common functionality** in [CommonTest](./kmp/src/commonTest/kotlin); +- **test platform-specific functionality** in each platform's test source set (`Test`) -> To run the tests for all supported targets, use the command: -> -> `./gradlew kmp:allTests` +To run the tests for all supported targets, use the command: + +```bash +./gradlew kmp:allTests +``` > [!IMPORTANT] > There's currently a Native target's dependency issue, @@ -110,7 +141,7 @@ essentially acting as a consumer. ```bash # from root node js-app/src/main/js/server.mjs -# take a look at the express paths and PORT configured in `server.mjs` +# take a look at the express paths and PORT configured in the server # open an HTTP client and access http://localhost:PORT ``` @@ -173,8 +204,8 @@ the dependencies must be added to the `dependencies` block of the `build.gradle. ```kotlin dependencies { - // Install npm dependencies - implementation(npm("randomstring", "1.3.0")) + // Install npm dependencies + implementation(npm("randomstring", "1.3.0")) } ``` @@ -204,9 +235,9 @@ randomstring.generate(7); @JsModule("randomstring") @JsNonModule external object RandomStringFromNpm { - fun generate( - length: Int = definedExternally, - ): String + fun generate( + length: Int = definedExternally, + ): String } ``` @@ -251,7 +282,7 @@ external object RandomStringFromNpm { node kotlin-js-interop/src/main/js/importing.mjs ``` -#### References +### References - [Kotlinlang: JS to Kotlin Interop](https://kotlinlang.org/docs/js-to-kotlin-interop.html) - [Kotlinlang: Kotlin to JS Interop](https://kotlinlang.org/docs/js-interop.html) @@ -261,9 +292,19 @@ node kotlin-js-interop/src/main/js/importing.mjs ## Ktor Framework +> [Ktor](https://ktor.io) is a modular framework for developing asynchronous server and client applications. +> +> Developed by _JetBrains_, it was built with pure _Kotlin_ and is integrated with +> the [Coroutines](https://github.com/Kotlin/kotlinx.coroutines) +> system. This system allows asynchronous code to be defined sequentially +> and can be executed without blocking threads, taking greater advantage of the computing system +> available + Module: [ktor](./ktor) -### Launching the Application +### Server + +#### Launching the Application The application can be launched using the `Application` class. @@ -275,9 +316,9 @@ fun main() { } ``` -### Define Application Module +#### Define Application Module -In _Ktor_, the application module is using the `Application` class. +In _Ktor_, the application module is defined using the `Application` class. ```kotlin fun Application.module() { @@ -285,9 +326,10 @@ fun Application.module() { } ``` -### Installing Plugins +#### Installing Plugins -Each plugin has its own configuration, which can be set using the `install` function. +A plugin can be installed using the `install` function and configured using its **last parameter function** (_trailing +lambda_). ```kotlin fun Application.module() { @@ -313,7 +355,7 @@ implementation("io.ktor:ktor-server-call-logging") implementation("io.ktor:ktor-server-websockets") ``` -### Defining Routes +#### Defining Routes Routes can be defined using the `routing` function. @@ -331,41 +373,34 @@ fun Application.module() { } ``` -### Testing the Application +#### Testing the Application -To test the application, the `testApplication` function can be used which exposes a `client` object that -can be used to perform requests to the server. +To test the application, you can utilize the `testApplication` function, which provides access to a `client` object for +making requests to the server. Example: ```kotlin testApplication { val log = arrayListOf() - // We perform a test websocket connection to this route. Effectively acting as a client. // The [incoming] parameter allows receiving frames, while the [outgoing] allows sending frames to the server. val client = client.config { install(WebSockets) } - client.webSocket("/ws") { - // Send a HELLO message outgoing.send(Frame.Text("HELLO")) - - // We then receive two messages (the message notifying that the member joined, and the message we sent echoed to us) for (n in 0 until 2) { log += (incoming.receive() as Frame.Text).readText() } } - - // asserts assertEquals(listOf("Member joined", "HELLO"), log) } ``` ### Client -Similar to the `Application` class, +Similar to the `Application` class as seen in the [Server](#server) section, the `HttpClient` class can be used to perform requests to a server and install plugins. ```kotlin @@ -405,3 +440,7 @@ val stringBody: String = httpResponse.body() ``` More examples [at](https://ktor.io/docs/response.html). + +### Demonstration + +TODO \ No newline at end of file diff --git a/convention-plugins/build.gradle.kts b/convention-plugins/build.gradle.kts index 64ac86b..cb339ee 100644 --- a/convention-plugins/build.gradle.kts +++ b/convention-plugins/build.gradle.kts @@ -6,6 +6,8 @@ dependencies { implementation(libs.nexus.publish) } -kotlin { - jvmToolchain(17) +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } } diff --git a/convention-plugins/src/main/kotlin/root.publication.gradle.kts b/convention-plugins/src/main/kotlin/root.publication.gradle.kts index d83953b..825c9e1 100644 --- a/convention-plugins/src/main/kotlin/root.publication.gradle.kts +++ b/convention-plugins/src/main/kotlin/root.publication.gradle.kts @@ -3,7 +3,7 @@ plugins { } allprojects { - group = "kresi.experiments" + group = "kresil-experiments" version = "0.0.1" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c85a1f..509c4a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmp/build.gradle.kts b/kmp/build.gradle.kts index 2dc7a1e..e3fdfc8 100644 --- a/kmp/build.gradle.kts +++ b/kmp/build.gradle.kts @@ -5,6 +5,11 @@ plugins { kotlin("plugin.serialization") version "1.9.22" } +repositories { + mavenCentral() + google() +} + kotlin { applyDefaultHierarchyTemplate() jvm() @@ -104,4 +109,24 @@ android { defaultConfig { minSdk = libs.versions.android.minSdk.get().toInt() } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + /*sourceSets.all { + java.srcDirs(file("src/android${name.capitalize()}/kotlin")) + res.srcDirs(file("src/android${name.capitalize()}/res")) + resources.srcDirs(file("src/android${name.capitalize()}/resources")) + manifest.srcFile(file("src/android${name.capitalize()}/AndroidManifest.xml")) + }*/ + sourceSets { + getByName("main") { + java.srcDirs("src/androidMain/kotlin") + res.srcDirs("src/androidMain/res") + } + getByName("test") { + java.srcDirs("src/androidTest/kotlin") + res.srcDirs("src/androidTest/res") + } + } } diff --git a/kmp/src/androidMain/kotlin/models/Book.android.kt b/kmp/src/androidMain/kotlin/models/Book.android.kt new file mode 100644 index 0000000..8fe6aa4 --- /dev/null +++ b/kmp/src/androidMain/kotlin/models/Book.android.kt @@ -0,0 +1,4 @@ +package models + +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +actual data class Book actual constructor(val title: String, val author: String) \ No newline at end of file diff --git a/kmp/src/androidMain/kotlin/Platform.android.kt b/kmp/src/androidMain/kotlin/target/Platform.android.kt similarity index 100% rename from kmp/src/androidMain/kotlin/Platform.android.kt rename to kmp/src/androidMain/kotlin/target/Platform.android.kt diff --git a/kmp/src/androidUnitTest/kotlin/AndroidPlatformTest.kt b/kmp/src/androidUnitTest/kotlin/AndroidPlatformTest.kt deleted file mode 100644 index 0d4654a..0000000 --- a/kmp/src/androidUnitTest/kotlin/AndroidPlatformTest.kt +++ /dev/null @@ -1,14 +0,0 @@ -import target.Platform -import target.PlatformType -import target.Target -import kotlin.test.Test -import kotlin.test.assertEquals - -class AndroidPlatformTest { - - @Test - fun testTargetCorrespondsToCurrentPlatform() { - val target = Target { Platform() } - assertEquals(PlatformType.Android, target.getPlatform().type) - } -} diff --git a/kmp/src/commonMain/kotlin/models/Book.kt b/kmp/src/commonMain/kotlin/models/Book.kt index 5b9bb2f..25fa507 100644 --- a/kmp/src/commonMain/kotlin/models/Book.kt +++ b/kmp/src/commonMain/kotlin/models/Book.kt @@ -4,5 +4,5 @@ package models * A simple book model. * Needs to be marked expect because of js export */ -@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING", "NO_ACTUAL_FOR_EXPECT") expect class Book(title: String, author: String) \ No newline at end of file diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 726ba83..0ffe06d 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -390,13 +390,6 @@ abab@^2.0.6: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -abort-controller@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1008,11 +1001,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -1856,13 +1844,6 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -2561,11 +2542,6 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -2654,11 +2630,6 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - webpack-cli@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.0.tgz#abc4b1f44b50250f2632d8b8b536cfe2f6257891" @@ -2790,14 +2761,6 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - which@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -2836,11 +2799,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - ws@^8.13.0: version "8.16.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" diff --git a/ktor/build.gradle.kts b/ktor/build.gradle.kts index cb23fb3..f561e51 100644 --- a/ktor/build.gradle.kts +++ b/ktor/build.gradle.kts @@ -1,39 +1,34 @@ -import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi -import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDistributionDsl -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21") - } +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidLibrary) } repositories { mavenCentral() -} - -plugins { - id("kotlin-multiplatform") + google() } kotlin { - @OptIn(DeprecatedTargetPresetApi::class, InternalKotlinGradlePluginApi::class) - targets { - js("frontend", IR) { - browser { - testTask { enabled = false } - - @OptIn(ExperimentalDistributionDsl::class) - distribution { - directory = file("$projectDir/src/backendMain/resources/web") - } - binaries.executable() + applyDefaultHierarchyTemplate() + jvm("backendJvm") // this creates both Main and Test source sets + androidTarget("frontendAndroid") { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + js("frontendJs", IR) { + browser { + testTask { enabled = false } + @OptIn(ExperimentalDistributionDsl::class) + distribution { + directory = file("$projectDir/src/backendJVMMain/resources/web") } + binaries.executable() } - jvm("backend") } sourceSets.forEach { @@ -43,9 +38,23 @@ kotlin { } sourceSets { - val backendMain by getting { + + val commonMain by getting { + dependencies { + + } + } + + val commonTest by getting { + dependencies { + implementation("org.jetbrains.kotlin:kotlin-test") + } + } + + val backendJvmMain by getting { + dependsOn(commonMain) dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.21") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.22") implementation("io.ktor:ktor-server-netty") implementation("io.ktor:ktor-server-websockets") implementation("io.ktor:ktor-server-call-logging") @@ -56,21 +65,49 @@ kotlin { } } - val backendTest by getting { + val backendJvmTest by getting { + dependsOn(commonTest) dependencies { implementation("io.ktor:ktor-server-test-host") implementation("io.ktor:ktor-client-websockets") - implementation("org.jetbrains.kotlin:kotlin-test") } } - val frontendMain by getting { + val frontendMain by creating { + dependsOn(commonMain) + dependencies { + + } + } + + val frontendJsMain by getting { + dependsOn(frontendMain) dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-js") implementation("io.ktor:ktor-client-websockets") + implementation("org.jetbrains.kotlin:kotlin-stdlib-js") implementation("io.ktor:ktor-client-js") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:1.6.4") } } + + val frontendAndroidMain by getting { + dependsOn(frontendMain) + dependencies { + + } + } } } + +android { + compileSdk = 32 + // sourceSets["main"].manifest.srcFile("src/frontendAndroidMain/AndroidManifest.xml") + defaultConfig { + minSdk = 21 + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + namespace = "kresil-experiments" +} \ No newline at end of file diff --git a/ktor/src/backendMain/.gitignore b/ktor/src/backendJvmMain/.gitignore similarity index 100% rename from ktor/src/backendMain/.gitignore rename to ktor/src/backendJvmMain/.gitignore diff --git a/ktor/src/backendMain/kotlin/Main.kt b/ktor/src/backendJvmMain/kotlin/Main.kt similarity index 100% rename from ktor/src/backendMain/kotlin/Main.kt rename to ktor/src/backendJvmMain/kotlin/Main.kt diff --git a/ktor/src/backendMain/kotlin/application/ChatApplication.kt b/ktor/src/backendJvmMain/kotlin/application/ChatApplication.kt similarity index 100% rename from ktor/src/backendMain/kotlin/application/ChatApplication.kt rename to ktor/src/backendJvmMain/kotlin/application/ChatApplication.kt diff --git a/ktor/src/backendMain/kotlin/application/ChatServer.kt b/ktor/src/backendJvmMain/kotlin/application/ChatServer.kt similarity index 100% rename from ktor/src/backendMain/kotlin/application/ChatServer.kt rename to ktor/src/backendJvmMain/kotlin/application/ChatServer.kt diff --git a/ktor/src/backendMain/kotlin/application/WebSocketServerHandler.kt b/ktor/src/backendJvmMain/kotlin/application/WebSocketServerHandler.kt similarity index 100% rename from ktor/src/backendMain/kotlin/application/WebSocketServerHandler.kt rename to ktor/src/backendJvmMain/kotlin/application/WebSocketServerHandler.kt diff --git a/ktor/src/backendMain/kotlin/application/models/ChatSession.kt b/ktor/src/backendJvmMain/kotlin/application/models/ChatSession.kt similarity index 100% rename from ktor/src/backendMain/kotlin/application/models/ChatSession.kt rename to ktor/src/backendJvmMain/kotlin/application/models/ChatSession.kt diff --git a/ktor/src/backendMain/kotlin/plugins/Headers.kt b/ktor/src/backendJvmMain/kotlin/plugins/Headers.kt similarity index 100% rename from ktor/src/backendMain/kotlin/plugins/Headers.kt rename to ktor/src/backendJvmMain/kotlin/plugins/Headers.kt diff --git a/ktor/src/backendMain/kotlin/plugins/Interceptors.kt b/ktor/src/backendJvmMain/kotlin/plugins/Interceptors.kt similarity index 100% rename from ktor/src/backendMain/kotlin/plugins/Interceptors.kt rename to ktor/src/backendJvmMain/kotlin/plugins/Interceptors.kt diff --git a/ktor/src/backendMain/kotlin/plugins/Monitoring.kt b/ktor/src/backendJvmMain/kotlin/plugins/Monitoring.kt similarity index 99% rename from ktor/src/backendMain/kotlin/plugins/Monitoring.kt rename to ktor/src/backendJvmMain/kotlin/plugins/Monitoring.kt index 3942afc..ba66146 100644 --- a/ktor/src/backendMain/kotlin/plugins/Monitoring.kt +++ b/ktor/src/backendJvmMain/kotlin/plugins/Monitoring.kt @@ -1,3 +1,4 @@ + package plugins import io.ktor.server.application.* diff --git a/ktor/src/backendMain/kotlin/plugins/Sessions.kt b/ktor/src/backendJvmMain/kotlin/plugins/Sessions.kt similarity index 100% rename from ktor/src/backendMain/kotlin/plugins/Sessions.kt rename to ktor/src/backendJvmMain/kotlin/plugins/Sessions.kt diff --git a/ktor/src/backendMain/kotlin/plugins/StatusPages.kt b/ktor/src/backendJvmMain/kotlin/plugins/StatusPages.kt similarity index 100% rename from ktor/src/backendMain/kotlin/plugins/StatusPages.kt rename to ktor/src/backendJvmMain/kotlin/plugins/StatusPages.kt diff --git a/ktor/src/backendMain/kotlin/plugins/WebSockets.kt b/ktor/src/backendJvmMain/kotlin/plugins/WebSockets.kt similarity index 100% rename from ktor/src/backendMain/kotlin/plugins/WebSockets.kt rename to ktor/src/backendJvmMain/kotlin/plugins/WebSockets.kt diff --git a/ktor/src/backendMain/kotlin/router/Routing.kt b/ktor/src/backendJvmMain/kotlin/router/Routing.kt similarity index 100% rename from ktor/src/backendMain/kotlin/router/Routing.kt rename to ktor/src/backendJvmMain/kotlin/router/Routing.kt diff --git a/ktor/src/backendMain/resources/application.conf b/ktor/src/backendJvmMain/resources/application.conf similarity index 100% rename from ktor/src/backendMain/resources/application.conf rename to ktor/src/backendJvmMain/resources/application.conf diff --git a/ktor/src/backendMain/resources/logback.xml b/ktor/src/backendJvmMain/resources/logback.xml similarity index 100% rename from ktor/src/backendMain/resources/logback.xml rename to ktor/src/backendJvmMain/resources/logback.xml diff --git a/ktor/src/backendMain/resources/web/index.html b/ktor/src/backendJvmMain/resources/web/index.html similarity index 100% rename from ktor/src/backendMain/resources/web/index.html rename to ktor/src/backendJvmMain/resources/web/index.html diff --git a/ktor/src/backendTest/kotlin/ChatApplicationTest.kt b/ktor/src/backendJvmTest/kotlin/ChatApplicationTest.kt similarity index 100% rename from ktor/src/backendTest/kotlin/ChatApplicationTest.kt rename to ktor/src/backendJvmTest/kotlin/ChatApplicationTest.kt diff --git a/ktor/src/frontendMain/kotlin/Main.kt b/ktor/src/frontendJsMain/kotlin/Main.kt similarity index 80% rename from ktor/src/frontendMain/kotlin/Main.kt rename to ktor/src/frontendJsMain/kotlin/Main.kt index 018befb..032fd58 100644 --- a/ktor/src/frontendMain/kotlin/Main.kt +++ b/ktor/src/frontendJsMain/kotlin/Main.kt @@ -1,3 +1,6 @@ +import connection.WsClient +import connection.dom.ChatDOMHandler +import connection.initConnection import io.ktor.client.* import io.ktor.client.plugins.websocket.* import kotlinx.coroutines.DelicateCoroutinesApi diff --git a/ktor/src/frontendMain/kotlin/Connection.kt b/ktor/src/frontendJsMain/kotlin/connection/Connection.kt similarity index 93% rename from ktor/src/frontendMain/kotlin/Connection.kt rename to ktor/src/frontendJsMain/kotlin/connection/Connection.kt index a3d597d..401706c 100644 --- a/ktor/src/frontendMain/kotlin/Connection.kt +++ b/ktor/src/frontendJsMain/kotlin/connection/Connection.kt @@ -1,4 +1,6 @@ -import ChatDOMHandler.appendMessage +package connection + +import connection.dom.ChatDOMHandler.appendMessage import io.ktor.client.plugins.websocket.* import kotlinx.browser.window import kotlinx.coroutines.DelicateCoroutinesApi diff --git a/ktor/src/frontendMain/kotlin/WsClient.kt b/ktor/src/frontendJsMain/kotlin/connection/WsClient.kt similarity index 97% rename from ktor/src/frontendMain/kotlin/WsClient.kt rename to ktor/src/frontendJsMain/kotlin/connection/WsClient.kt index 1d7a4c2..670ee1d 100644 --- a/ktor/src/frontendMain/kotlin/WsClient.kt +++ b/ktor/src/frontendJsMain/kotlin/connection/WsClient.kt @@ -1,3 +1,5 @@ +package connection + import io.ktor.client.* import io.ktor.client.plugins.websocket.* import io.ktor.http.* diff --git a/ktor/src/frontendMain/kotlin/ChatDOMHandler.kt b/ktor/src/frontendJsMain/kotlin/dom/ChatDOMHandler.kt similarity index 97% rename from ktor/src/frontendMain/kotlin/ChatDOMHandler.kt rename to ktor/src/frontendJsMain/kotlin/dom/ChatDOMHandler.kt index 177fbb2..82e07f3 100644 --- a/ktor/src/frontendMain/kotlin/ChatDOMHandler.kt +++ b/ktor/src/frontendJsMain/kotlin/dom/ChatDOMHandler.kt @@ -1,3 +1,6 @@ +package connection.dom + +import connection.WsClient import kotlinx.browser.document import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope