Compare commits

...

8 Commits

Author SHA1 Message Date
546736690c continue reborn :( 2024-08-26 23:58:53 +06:00
e98a484c4d start second (or third?) reborn 2024-02-16 13:40:47 +06:00
ff973e63fc start migration onto ktor-based serialization of data 2022-06-12 18:54:28 +06:00
399405a4fb update dependencies 2022-06-12 18:18:07 +06:00
b7e5e2745d update dependencies 2022-06-05 00:30:41 +06:00
92cd98b80f add client subfeature 2022-05-21 14:48:53 +06:00
b73df49925 fixes in auth 2022-05-20 00:15:49 +06:00
f835dc1557 update tgbotapi 2022-05-19 00:01:50 +06:00
124 changed files with 533 additions and 523 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.idea .idea
.kotlin
out/* out/*
*.iml *.iml
target target

View File

@@ -1,12 +1,14 @@
## Структура проекта ## Структура проекта
* **Features** - набор **законченных** фич проекта. Считается, что любая фича, находящаяся в мастере может быть добавлена в * **Features** - набор **законченных** фич проекта. Считается, что любая фича, находящаяся в мастере может быть добавлена в
клиент и использована в нем. Исключением является `common` - это набор вещей, используемых везде. В подпунктах представлены клиент и использована в нем. Исключением является `common` - это набор вещей, используемых везде.
части, на которые *обычно* разделяется фича * Части, на которые *обычно* разделяется фича
* Common - общая для фичи часть. Тут, как правило, хранятся конвенции путей для сетевых соединений, общие типы и пр. * Common - общая для фичи часть. Тут, как правило, хранятся конвенции путей для сетевых соединений, общие типы и пр.
* Server - часть, включаемая в сервер для подключения фичи. Обычно содержит работу с бд, определение модулей сервера и пр. * Server - часть, включаемая в сервер для подключения фичи. Обычно содержит работу с бд, определение модулей сервера и пр.
* Client - часть с клиентским кодом. В большинстве своём включает работу с сервером, MVVM часть (View при этом должны * Client - часть с клиентским кодом. В большинстве своём включает работу с сервером, MVVM часть (View при этом должны
находиться в платформенной части, если их нельзя вынести в сommon часть клиента) находиться в платформенной части, если их нельзя вынести в сommon часть клиента)
* Также существует фича `client`, которая не является фичей самой по-себе. Фактически, это набор разных фич, который системно
отсутствуют в бэке и используются в основном для пробрасывания удобных `API` и `View` для клиента
* **Services** - модули, отвечающие за клиент-серверную работу фич с точки зрения их взаимодействия. Например, в рамках сервисов * **Services** - модули, отвечающие за клиент-серверную работу фич с точки зрения их взаимодействия. Например, в рамках сервисов
должен быть добавлен модуль для постов - именно через сервисы будет происходить создание поста, его редактирование и удаление должен быть добавлен модуль для постов - именно через сервисы будет происходить создание поста, его редактирование и удаление
* **Client** - итоговый клиент. На момент написания этой доки (`Пн окт 25 12:56:41 +06 2021`) предполагается два варианта: * **Client** - итоговый клиент. На момент написания этой доки (`Пн окт 25 12:56:41 +06 2021`) предполагается два варианта:

View File

@@ -23,6 +23,7 @@ allprojects {
mavenCentral() mavenCentral()
google() google()
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" } maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
} }
} }

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -58,5 +58,6 @@
"semver": "^7.3.2", "semver": "^7.3.2",
"svgo": "^2.8.0", "svgo": "^2.8.0",
"watch-run": "^1.2.5" "watch-run": "^1.2.5"
} },
"packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
} }

View File

@@ -1,39 +1,16 @@
apply plugin: 'com.getkeepsafe.dexcount' apply plugin: 'com.getkeepsafe.dexcount'
android { android {
ext {
jvmKotlinFolderFile = {
String sep = File.separator
return new File("${project.projectDir}${sep}src${sep}jvmMain${sep}kotlin")
}
enableIncludingJvmCodeInAndroidPart = {
File jvmKotlinFolder = jvmKotlinFolderFile()
if (jvmKotlinFolder.exists()) {
android.sourceSets.main.java.srcDirs += jvmKotlinFolder.path
}
}
disableIncludingJvmCodeInAndroidPart = {
File jvmKotlinFolder = jvmKotlinFolderFile()
String[] oldDirs = android.sourceSets.main.java.srcDirs
android.sourceSets.main.java.srcDirs = []
for (oldDir in oldDirs) {
if (oldDir != jvmKotlinFolder.path) {
android.sourceSets.main.java.srcDirs += oldDir
}
}
}
}
compileSdkVersion libs.versions.android.props.compileSdk.get().toInteger() compileSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
buildToolsVersion libs.versions.android.props.buildTools.get() buildToolsVersion libs.versions.android.props.buildTools.get()
defaultConfig { defaultConfig {
minSdkVersion libs.versions.android.props.minSdk.get().toInteger() minSdkVersion libs.versions.android.props.minSdk.get().toInteger()
compileSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
targetSdkVersion libs.versions.android.props.compileSdk.get().toInteger() targetSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
versionCode "${android_code_version}".toInteger() versionCode "${android_code_version}".toInteger()
versionName "$version" versionName "$version"
namespace "${project.group}.${project.name}"
} }
buildTypes { buildTypes {
release { release {
@@ -51,18 +28,7 @@ android {
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_17
} }
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
sourceSets {
String sep = File.separator
main.java.srcDirs += "src${sep}main${sep}kotlin"
}
enableIncludingJvmCodeInAndroidPart()
} }

View File

@@ -13,21 +13,6 @@ allprojects {
projectByName(name) projectByName(name)
} }
allTargetsConfiguration = { ->
kotlin {
targets.all {
compilations.all {
kotlinOptions {
freeCompilerArgs += [
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true"
]
}
}
}
}
}
mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle" mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle"
mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle" mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle" mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -1,7 +1,6 @@
package dev.inmo.postssystem.features.auth.client package dev.inmo.postssystem.features.auth.client
import dev.inmo.micro_utils.common.Either import dev.inmo.micro_utils.common.Either
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.postssystem.features.auth.common.AuthKey import dev.inmo.postssystem.features.auth.common.AuthKey
import dev.inmo.postssystem.features.auth.common.AuthTokenInfo import dev.inmo.postssystem.features.auth.common.AuthTokenInfo
import dev.inmo.postssystem.features.common.common.AdditionalModules import dev.inmo.postssystem.features.common.common.AdditionalModules
@@ -27,7 +26,6 @@ fun createAuthorizedFeaturesDIModule(
installClientAuthenticator(serverUrl, get(), get(AuthorizedQualifiers.CredsQualifier), onAuthKeyUpdated, onUserRetrieved, onAuthKeyInvalidated) installClientAuthenticator(serverUrl, get(), get(AuthorizedQualifiers.CredsQualifier), onAuthKeyUpdated, onUserRetrieved, onAuthKeyInvalidated)
} }
} }
single { UnifiedRequester(get(), get()) }
single { StatusFeatureClient(get(AuthorizedQualifiers.ServerUrlQualifier), get()) } single { StatusFeatureClient(get(AuthorizedQualifiers.ServerUrlQualifier), get()) }
AdditionalModules.Authorized.modules.forEach { AdditionalModules.Authorized.modules.forEach {

View File

@@ -2,14 +2,14 @@ package dev.inmo.postssystem.features.auth.client
import dev.inmo.postssystem.features.auth.common.* import dev.inmo.postssystem.features.auth.common.*
import dev.inmo.postssystem.features.users.common.User import dev.inmo.postssystem.features.users.common.User
import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.ktor.client.bodyOrNull
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.*
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
class ClientAuthFeature( class ClientAuthFeature(
private val requester: UnifiedRequester, private val client: HttpClient,
baseUrl: String baseUrl: String
) : AuthFeature { ) : AuthFeature {
private val rootUrl = buildStandardUrl(baseUrl.dropLastWhile { it == '/' }, authRootPathPart) private val rootUrl = buildStandardUrl(baseUrl.dropLastWhile { it == '/' }, authRootPathPart)
@@ -26,28 +26,23 @@ class ClientAuthFeature(
authGetMePathPart authGetMePathPart
) )
constructor(client: HttpClient, rootUrl: String): this( override suspend fun auth(creds: AuthCreds): AuthTokenInfo? = client.post(
UnifiedRequester(client), fullAuthPath
rootUrl ) {
) setBody(creds)
}.bodyOrNull()
override suspend fun auth(creds: AuthCreds): AuthTokenInfo? = requester.unipost( override suspend fun refresh(refresh: RefreshToken): AuthTokenInfo? = client.post(
fullAuthPath, fullRefreshPath
AuthCreds.serializer() to creds, ) {
AuthTokenInfo.serializer().nullable setBody(refresh)
) }.bodyOrNull()
override suspend fun refresh(refresh: RefreshToken): AuthTokenInfo? = requester.unipost( override suspend fun getMe(authToken: AuthToken): User? = client.post(
fullRefreshPath, fullGetMePath
RefreshToken.serializer() to refresh, ) {
AuthTokenInfo.serializer().nullable setBody(authToken)
) }.bodyOrNull()
override suspend fun getMe(authToken: AuthToken): User? = requester.unipost(
fullGetMePath,
AuthToken.serializer() to authToken,
User.serializer().nullable
)
fun isAuthRequest(builder: HttpRequestBuilder): Boolean = builder.url.buildString().let { fun isAuthRequest(builder: HttpRequestBuilder): Boolean = builder.url.buildString().let {
it == fullAuthPath || it == fullRefreshPath it == fullAuthPath || it == fullRefreshPath

View File

@@ -37,7 +37,7 @@ fun HttpClientConfig<*>.installClientAuthenticator(
}.onSecond { }.onSecond {
currentRefreshToken = it.refresh currentRefreshToken = it.refresh
} }
val creds = initialAuthKey.t1 as? AuthCreds val creds = initialAuthKey.t1OrNull as? AuthCreds
var userRefreshJob: Job? = null var userRefreshJob: Job? = null
install("Auth Token Refresher") { install("Auth Token Refresher") {

View File

@@ -8,8 +8,9 @@ import dev.inmo.postssystem.features.auth.client.ui.*
import dev.inmo.postssystem.features.common.common.* import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMExceptionHandler import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMExceptionHandler
import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMState import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMState
import kotlin.js.JsExport
val defaultModuleLoader = DefaultModuleLoader { internal fun CommonAuthModuleLoader() = DefaultModuleLoader {
single<AuthSettings> { DefaultAuthSettings(get(DefaultQualifiers.SettingsQualifier), get(), getKoin(), get()) } single<AuthSettings> { DefaultAuthSettings(get(DefaultQualifiers.SettingsQualifier), get(), getKoin(), get()) }
singleWithRandomQualifier { singleWithRandomQualifier {

View File

@@ -29,7 +29,7 @@ val loader = DefaultModuleLoader {
strictlyOn(get<AuthView>()) strictlyOn(get<AuthView>())
} }
} }
} } + CommonAuthModuleLoader()
class AuthView( class AuthView(
private val viewModel: AuthUIViewModel, private val viewModel: AuthUIViewModel,

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.auth.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.auth.common"/>

View File

@@ -2,7 +2,7 @@ package dev.inmo.postssystem.features.auth.server
import dev.inmo.postssystem.features.auth.common.* import dev.inmo.postssystem.features.auth.common.*
import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService
import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator import dev.inmo.postssystem.features.common.server.ApplicationAuthenticationConfigurator
import dev.inmo.postssystem.features.users.common.User import dev.inmo.postssystem.features.users.common.User
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.server.* import dev.inmo.micro_utils.ktor.server.*
@@ -10,6 +10,7 @@ import dev.inmo.micro_utils.ktor.server.configurators.*
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call import io.ktor.server.application.call
import io.ktor.server.auth.* import io.ktor.server.auth.*
import io.ktor.server.request.receive
import io.ktor.server.response.respond import io.ktor.server.response.respond
import io.ktor.server.routing.* import io.ktor.server.routing.*
import io.ktor.server.sessions.sessions import io.ktor.server.sessions.sessions
@@ -24,84 +25,72 @@ fun User.principal() = AuthUserPrincipal(this)
class AuthenticationRoutingConfigurator( class AuthenticationRoutingConfigurator(
private val authFeature: AuthFeature, private val authFeature: AuthFeature,
private val authTokensService: AuthTokensService, private val authTokensService: AuthTokensService
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element { ) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
unifiedRouter.apply { route(authRootPathPart) {
route(authRootPathPart) { post(authAuthPathPart) {
post(authAuthPathPart) { safely(
safely( {
{ // TODO:: add error info
// TODO:: add error info it.printStackTrace()
it.printStackTrace() call.respond(
call.respond( HttpStatusCode.InternalServerError,
HttpStatusCode.InternalServerError, "Something went wrong"
"Something went wrong"
)
}
) {
val creds = uniload(AuthCreds.serializer())
val tokenInfo = authFeature.auth(creds)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
}
}
}
post (authRefreshPathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
val refreshToken = uniload(RefreshToken.serializer())
val tokenInfo = authFeature.refresh(refreshToken)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
}
}
}
post(authGetMePathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
unianswer(
User.serializer().nullable,
authFeature.getMe(
uniload(AuthToken.serializer())
)
) )
} }
) {
val creds = call.receive<AuthCreds>()
val tokenInfo = authFeature.auth(creds)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
call.respond(tokenInfo)
}
}
}
post (authRefreshPathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
val refreshToken = call.receive<RefreshToken>()
val tokenInfo = authFeature.refresh(refreshToken)
if (tokenInfo == null) {
if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
call.respond(tokenInfo)
}
}
}
post(authGetMePathPart) {
safely(
{
// TODO:: add error info
call.respond(
HttpStatusCode.InternalServerError,
"Something went wrong"
)
}
) {
call.respond(
authFeature.getMe(call.receive()) ?: HttpStatusCode.NoContent
)
} }
} }
} }

View File

@@ -1,6 +1,6 @@
package dev.inmo.postssystem.features.auth.server.tokens package dev.inmo.postssystem.features.auth.server.tokens
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import dev.inmo.postssystem.features.auth.common.AuthToken import dev.inmo.postssystem.features.auth.common.AuthToken
import dev.inmo.postssystem.features.auth.common.RefreshToken import dev.inmo.postssystem.features.auth.common.RefreshToken
import dev.inmo.postssystem.features.users.common.UserId import dev.inmo.postssystem.features.users.common.UserId

View File

@@ -1,7 +1,7 @@
package dev.inmo.postssystem.features.auth.server.tokens package dev.inmo.postssystem.features.auth.server.tokens
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import com.soywiz.klock.milliseconds import korlibs.time.milliseconds
import dev.inmo.postssystem.features.auth.common.* import dev.inmo.postssystem.features.auth.common.*
import dev.inmo.postssystem.features.common.common.Milliseconds import dev.inmo.postssystem.features.common.common.Milliseconds
import dev.inmo.postssystem.features.users.common.* import dev.inmo.postssystem.features.users.common.*

View File

@@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.client.template.common")
api project(":postssystem.features.common.client")
}
}
}
}

View File

@@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.common.common")
}
}
}
}

View File

@@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply from: "$mppJavaProjectPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.client.template.common")
api project(":postssystem.features.common.server")
}
}
}
}

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -49,12 +49,16 @@ fun baseKoin(
single { repoFactory() } single { repoFactory() }
single { defaultScope } single { defaultScope }
single(DefaultQualifiers.UIScopeQualifier) { get<CoroutineScope>().LinkedSupervisorScope(Dispatchers.Main) } single(DefaultQualifiers.UIScopeQualifier) { get<CoroutineScope>().LinkedSupervisorScope(Dispatchers.Main) }
single<StatesMachine<UIFSMState>>(UIFSMQualifier) { UIFSM(get()) { (this@single to this@UIFSM).apply(get( single<StatesMachine<UIFSMState>>(DefaultQualifiers.UIFSMQualifier) {
DefaultQualifiers.FSMHandlersBuilderQualifier UIFSM(get()) {
)) } } (this@single to this@UIFSM).apply(get(DefaultQualifiers.FSMHandlersBuilderQualifier))
}
AdditionalModules.Default.modules.forEach { }
it.apply { load() } } + AdditionalModules.Default.modules.map {
module {
with(it) {
load()
}
} }
} }
) )

View File

@@ -6,5 +6,5 @@ object DefaultQualifiers {
val SettingsQualifier = StringQualifier("Settings") val SettingsQualifier = StringQualifier("Settings")
val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder") val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder")
val UIScopeQualifier = StringQualifier("CoroutineScopeUI") val UIScopeQualifier = StringQualifier("CoroutineScopeUI")
val UIFSMQualifier = StringQualifier("FSM") val UIFSMQualifier = StringQualifier("UIFSM")
} }

View File

@@ -12,6 +12,15 @@ interface ModuleLoader {
} }
} }
operator fun ModuleLoader.plus(other: ModuleLoader) = ModuleLoader.ByCallback {
with(this@plus) {
load()
}
with (other) {
load()
}
}
fun DefaultModuleLoader(loadingBlock: Module.() -> Unit): ModuleLoader.ByCallback { fun DefaultModuleLoader(loadingBlock: Module.() -> Unit): ModuleLoader.ByCallback {
val newModuleLoader = ModuleLoader.ByCallback(loadingBlock) val newModuleLoader = ModuleLoader.ByCallback(loadingBlock)
AdditionalModules.Default.addModule(newModuleLoader) AdditionalModules.Default.addModule(newModuleLoader)

View File

@@ -6,8 +6,6 @@ import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo
import org.koin.core.qualifier.StringQualifier import org.koin.core.qualifier.StringQualifier
val UIFSMQualifier = StringQualifier("UIFSM")
fun UIFSM( fun UIFSM(
repo: DefaultStatesManagerRepo<UIFSMState>, repo: DefaultStatesManagerRepo<UIFSMState>,
handlersSetter: FSMBuilder<UIFSMState>.() -> Unit handlersSetter: FSMBuilder<UIFSMState>.() -> Unit

View File

@@ -1,8 +1,8 @@
package dev.inmo.postssystem.features.common.common.ui package dev.inmo.postssystem.features.common.common.ui
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import com.soywiz.klock.ISO8601 import korlibs.time.ISO8601
import org.jetbrains.compose.web.dom.Text import org.jetbrains.compose.web.dom.Text
object DateTimeView { object DateTimeView {

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.common.client"/>

View File

@@ -1,6 +1,6 @@
package dev.inmo.postssystem.features.common.common package dev.inmo.postssystem.features.common.common
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer import kotlinx.serialization.Serializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer

View File

@@ -1,6 +1,7 @@
package dev.inmo.postssystem.features.common.common package dev.inmo.postssystem.features.common.common
import dev.inmo.micro_utils.common.MPPFile import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.common.filesize
import io.ktor.utils.io.core.* import io.ktor.utils.io.core.*
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ByteArraySerializer import kotlinx.serialization.builtins.ByteArraySerializer
@@ -27,9 +28,18 @@ class BytesBasedInputProvider(
} }
} }
@Serializable(SimpleInputProviderSerializer::class) internal interface FileInputProvider : SimpleInputProvider {
expect class FileBasedInputProvider : SimpleInputProvider {
val file: MPPFile val file: MPPFile
override val contentBytes: Long?
get() = file.filesize
}
@Serializable(SimpleInputProviderSerializer::class)
expect class FileBasedInputProvider : FileInputProvider {
override val file: MPPFile
override fun invoke(): Input
} }
@Serializable(SimpleInputProviderSerializer::class) @Serializable(SimpleInputProviderSerializer::class)

View File

@@ -7,12 +7,9 @@ import kotlinx.serialization.Serializable
@Serializable(SimpleInputProviderSerializer::class) @Serializable(SimpleInputProviderSerializer::class)
actual class FileBasedInputProvider internal constructor( actual class FileBasedInputProvider internal constructor(
actual val file: MPPFile actual override val file: MPPFile
) : SimpleInputProvider { ) : FileInputProvider {
override val contentBytes: Long actual override fun invoke(): Input = error("Files inputs must not be used directly")
get() = file.filesize
override fun invoke(): Input = error("Files inputs must not be used directly")
} }
fun MPPFile.inputProvider() = FileBasedInputProvider(this) fun MPPFile.inputProvider() = FileBasedInputProvider(this)

View File

@@ -8,10 +8,8 @@ import kotlinx.serialization.Serializable
@Serializable(SimpleInputProviderSerializer::class) @Serializable(SimpleInputProviderSerializer::class)
actual class FileBasedInputProvider( actual class FileBasedInputProvider(
actual val file: MPPFile actual override val file: MPPFile
) : SimpleInputProvider { ) : FileInputProvider {
override val contentBytes: Long?
get() = file.filesize
override fun invoke(): Input = file.inputStream().asInput() actual override fun invoke(): Input = file.inputStream().asInput()
} }

View File

@@ -1,6 +1,7 @@
package dev.inmo.postssystem.features.common.common package dev.inmo.postssystem.features.common.common
import org.koin.core.definition.Definition import org.koin.core.definition.Definition
import org.koin.core.definition.KoinDefinition
import org.koin.core.instance.InstanceFactory import org.koin.core.instance.InstanceFactory
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.qualifier.Qualifier import org.koin.core.qualifier.Qualifier
@@ -11,6 +12,6 @@ inline fun <reified T : Any> Module.singleWithBinds(
qualifier: Qualifier? = null, qualifier: Qualifier? = null,
createdAtStart: Boolean = false, createdAtStart: Boolean = false,
noinline definition: Definition<T> noinline definition: Definition<T>
): Pair<Module, InstanceFactory<*>> { ): KoinDefinition<*> {
return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.toTypedArray()) return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.toTypedArray())
} }

View File

@@ -0,0 +1,10 @@
package dev.inmo.postssystem.features.common.common
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.common.filename
import dev.inmo.micro_utils.mime_types.*
actual val MPPFile.mimeType: MimeType
get() {
return getMimeTypeOrAny(filename.extension)
}

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.common.common"/>

View File

@@ -0,0 +1,11 @@
package dev.inmo.postssystem.features.common.common
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.common.filename
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.micro_utils.mime_types.getMimeTypeOrAny
actual val MPPFile.mimeType: MimeType
get() {
return getMimeTypeOrAny(filename.extension)
}

View File

@@ -1,4 +1,4 @@
package dev.inmo.postssystem.features.common.server.sessions package dev.inmo.postssystem.features.common.server
import dev.inmo.micro_utils.ktor.server.configurators.KtorApplicationConfigurator import dev.inmo.micro_utils.ktor.server.configurators.KtorApplicationConfigurator
import io.ktor.server.application.Application import io.ktor.server.application.Application

View File

@@ -1,8 +1,9 @@
package dev.inmo.postssystem.features.common.server.sessions package dev.inmo.postssystem.features.common.server
import org.koin.core.qualifier.StringQualifier import org.koin.core.qualifier.StringQualifier
object Qualifiers { object Qualifiers {
val filesFolderQualifier = StringQualifier("filesFolder") val filesFolderQualifier = StringQualifier("filesFolder")
val commonFilesFolderQualifier = StringQualifier("commonFilesFolder")
val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory") val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory")
} }

View File

@@ -1,4 +1,4 @@
package dev.inmo.postssystem.features.common.server.sessions package dev.inmo.postssystem.features.common.server
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import org.koin.core.module.Module import org.koin.core.module.Module

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.binary.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.binary.common"/>

View File

@@ -3,8 +3,8 @@ package dev.inmo.postssystem.features.content.binary.server
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
import dev.inmo.postssystem.features.common.common.singleWithBinds import dev.inmo.postssystem.features.common.common.singleWithBinds
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
import dev.inmo.postssystem.features.common.server.sessions.Qualifiers import dev.inmo.postssystem.features.common.server.Qualifiers
import dev.inmo.postssystem.features.common.server.sessions.ServerModuleLoader import dev.inmo.postssystem.features.common.server.ServerModuleLoader
import dev.inmo.postssystem.features.content.common.BinaryContent import dev.inmo.postssystem.features.content.common.BinaryContent
import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper
import dev.inmo.postssystem.features.files.common.* import dev.inmo.postssystem.features.files.common.*

View File

@@ -6,7 +6,6 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.mime_types.KnownMimeTypes import dev.inmo.micro_utils.mime_types.KnownMimeTypes
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.postssystem.features.common.common.FileBasedInputProvider
import dev.inmo.postssystem.features.content.common.* import dev.inmo.postssystem.features.content.common.*
import dev.inmo.postssystem.features.content.server.storage.ServerContentStorage import dev.inmo.postssystem.features.content.server.storage.ServerContentStorage
import dev.inmo.postssystem.features.files.common.* import dev.inmo.postssystem.features.files.common.*

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.client"/>

View File

@@ -1,7 +1,6 @@
package dev.inmo.postssystem.features.content.common package dev.inmo.postssystem.features.content.common
import dev.inmo.micro_utils.common.FileName import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.mime_types.MimeType import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.postssystem.features.common.common.SimpleInputProvider import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.PolymorphicSerializer
@@ -30,6 +29,18 @@ data class BinaryContent(
) : Content ) : Content
val ContentSerializer = PolymorphicSerializer(Content::class) val ContentSerializer = PolymorphicSerializer(Content::class)
@Serializable
data class ContentWrapper(
val content: Content
)
@Serializable
data class ContentsWrapper(
val content: List<Content>
)
@Serializable
data class ContentsEithersWrapper(
val content: List<Either<ContentId, Content>>
)
/** /**
* Content which is already registered in database. Using its [id] you can retrieve all known * Content which is already registered in database. Using its [id] you can retrieve all known

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.common"/>

View File

@@ -3,6 +3,7 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose) alias(libs.plugins.compose)
alias(libs.plugins.kt.jb.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.content.text.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.content.content.text.common"/>

View File

@@ -1,7 +1,7 @@
package dev.inmo.postssystem.features.content.text.server package dev.inmo.postssystem.features.content.text.server
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
import dev.inmo.postssystem.features.common.server.sessions.ServerModuleLoader import dev.inmo.postssystem.features.common.server.ServerModuleLoader
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper
import dev.inmo.postssystem.features.content.text.common.TextContent import dev.inmo.postssystem.features.content.text.common.TextContent

View File

@@ -2,30 +2,29 @@ package dev.inmo.postssystem.features.files.client
import dev.inmo.postssystem.features.files.common.* import dev.inmo.postssystem.features.files.common.*
import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage
import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.ktor.client.bodyOrNull
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadStandardCrudRepo import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadCRUDRepoClient
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.post import io.ktor.client.request.*
import io.ktor.client.request.setBody
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.readBytes import io.ktor.client.statement.readBytes
import io.ktor.http.ContentType
import io.ktor.http.encodeURLQueryComponent
import kotlinx.serialization.BinaryFormat import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
class ClientReadFilesStorage( class ClientReadFilesStorage(
baseUrl: String, baseUrl: String,
private val client: HttpClient, private val client: HttpClient,
private val serialFormat: BinaryFormat private val serialFormat: BinaryFormat,
) : ReadFilesStorage, ReadCRUDRepo<MetaFileInfoStorageWrapper, FileId> by KtorReadStandardCrudRepo( contentType: ContentType
) : ReadFilesStorage, ReadCRUDRepo<MetaFileInfoStorageWrapper, FileId> by KtorReadCRUDRepoClient<MetaFileInfoStorageWrapper, FileId>(
buildStandardUrl(baseUrl, filesRootPathPart), buildStandardUrl(baseUrl, filesRootPathPart),
UnifiedRequester(client, serialFormat), client,
MetaFileInfoStorageWrapper.serializer(), contentType,
MetaFileInfoStorageWrapper.serializer().nullable, { it.string.encodeURLQueryComponent() }
FileId.serializer()
) { ) {
private val unifiedRequester = UnifiedRequester(client, serialFormat)
private val fullFilesPath = buildStandardUrl(baseUrl, filesRootPathPart) private val fullFilesPath = buildStandardUrl(baseUrl, filesRootPathPart)
private val fullFilesGetBytesPath = buildStandardUrl( private val fullFilesGetBytesPath = buildStandardUrl(
fullFilesPath, fullFilesPath,
@@ -38,12 +37,11 @@ class ClientReadFilesStorage(
override suspend fun getFullFileInfo( override suspend fun getFullFileInfo(
id: FileId id: FileId
): FullFileInfoStorageWrapper? = unifiedRequester.uniget( ): FullFileInfoStorageWrapper? = client.get(
buildStandardUrl( buildStandardUrl(
fullFilesPath, fullFilesPath,
filesGetFullFileInfoPathPart, filesGetFullFileInfoPathPart,
filesFileIdParameter to unifiedRequester.encodeUrlQueryValue(FileId.serializer(), id) filesFileIdParameter to id.string.encodeURLQueryComponent()
), )
FullFileInfoStorageWrapper.serializer().nullable ).bodyOrNull()
)
} }

View File

@@ -5,5 +5,5 @@ import dev.inmo.postssystem.features.auth.client.AuthorizedQualifiers
import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage
val loader = AuthorizedModuleLoader { val loader = AuthorizedModuleLoader {
single<ReadFilesStorage> { ClientReadFilesStorage(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get()) } single<ReadFilesStorage> { ClientReadFilesStorage(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get(), get()) }
} }

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.files.client"/>

View File

@@ -61,4 +61,8 @@ class DiskReadFilesStorage(
} }
) )
} }
override suspend fun getIdsByPagination(pagination: Pagination): PaginationResult<FileId> {
return metasKeyValueRepo.keys(pagination)
}
} }

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.files.common"/>

View File

@@ -4,10 +4,13 @@ import dev.inmo.postssystem.features.files.common.*
import dev.inmo.postssystem.features.files.common.storage.* import dev.inmo.postssystem.features.files.common.storage.*
import dev.inmo.micro_utils.ktor.server.* import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes import dev.inmo.micro_utils.repos.ktor.server.crud.*
import dev.inmo.micro_utils.repos.ktor.server.crud.configureWriteStandardCrudRepoRoutes import io.ktor.http.HttpStatusCode
import io.ktor.http.decodeURLQueryComponent
import io.ktor.server.application.call import io.ktor.server.application.call
import io.ktor.server.auth.authenticate import io.ktor.server.auth.authenticate
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.response.respondBytes import io.ktor.server.response.respondBytes
import io.ktor.server.routing.* import io.ktor.server.routing.*
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
@@ -15,47 +18,33 @@ import kotlinx.serialization.builtins.nullable
class FilesRoutingConfigurator( class FilesRoutingConfigurator(
private val filesStorage: ReadFilesStorage, private val filesStorage: ReadFilesStorage,
private val writeFilesStorage: WriteFilesStorage?, private val writeFilesStorage: WriteFilesStorage?,
private val unifierRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
constructor(filesStorage: FilesStorage, unifierRouter: UnifiedRouter) : this(filesStorage, filesStorage, unifierRouter) constructor(filesStorage: FilesStorage) : this(filesStorage, filesStorage)
override fun Route.invoke() { override fun Route.invoke() {
authenticate { authenticate {
route(filesRootPathPart) { route(filesRootPathPart) {
configureReadStandardCrudRepoRoutes( configureReadCRUDRepoRoutes(
filesStorage, filesStorage,
MetaFileInfoStorageWrapper.serializer(), ::FileId
MetaFileInfoStorageWrapper.serializer().nullable,
FileId.serializer(),
unifierRouter
) )
writeFilesStorage ?.let { writeFilesStorage ?.let {
configureWriteStandardCrudRepoRoutes( configureWriteCRUDRepoRoutes(writeFilesStorage)
writeFilesStorage,
FullFileInfoStorageWrapper.serializer(),
FullFileInfoStorageWrapper.serializer().nullable,
FullFileInfo.serializer(),
FileId.serializer(),
unifierRouter
)
} }
unifierRouter.apply { post(filesGetFilesPathPart) {
post(filesGetFilesPathPart) { call.respondBytes(
call.respondBytes( filesStorage.getBytes(
filesStorage.getBytes( call.receive()
uniload(FileId.serializer())
)
) )
} )
get(filesGetFullFileInfoPathPart) { }
unianswer( get(filesGetFullFileInfoPathPart) {
FullFileInfoStorageWrapper.serializer().nullable, call.respond(
filesStorage.getFullFileInfo( filesStorage.getFullFileInfo(
decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get FileId(call.getParameterOrSendError(filesFileIdParameter) ?.decodeURLQueryComponent() ?: return@get)
) ) ?: HttpStatusCode.NoContent
) )
}
} }
} }
} }

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.posts.client"/>

View File

@@ -1,6 +1,6 @@
package dev.inmo.postssystem.features.posts.common package dev.inmo.postssystem.features.posts.common
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import dev.inmo.postssystem.features.common.common.DateTimeSerializer import dev.inmo.postssystem.features.common.common.DateTimeSerializer
import dev.inmo.postssystem.features.content.common.Content import dev.inmo.postssystem.features.content.common.Content
import dev.inmo.postssystem.features.content.common.ContentId import dev.inmo.postssystem.features.content.common.ContentId

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.posts.common"/>

View File

@@ -1,6 +1,6 @@
package dev.inmo.postssystem.features.posts.server package dev.inmo.postssystem.features.posts.server
import com.soywiz.klock.DateTime import korlibs.time.DateTime
import dev.inmo.micro_utils.repos.exposed.* import dev.inmo.micro_utils.repos.exposed.*
import dev.inmo.postssystem.features.content.common.ContentId import dev.inmo.postssystem.features.content.common.ContentId
import dev.inmo.postssystem.features.posts.common.* import dev.inmo.postssystem.features.posts.common.*

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.publication.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.publication.common"/>

View File

@@ -1,17 +1,17 @@
package dev.inmo.postssystem.features.roles.client package dev.inmo.postssystem.features.roles.client
import dev.inmo.postssystem.features.roles.common.* import dev.inmo.postssystem.features.roles.common.*
import dev.inmo.micro_utils.ktor.client.UnifiedRequester import io.ktor.client.*
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
class ClientRolesStorage<T : Role>( class ClientRolesStorage<T : Role>(
private val baseUrl: String, private val baseUrl: String,
private val unifiedRequester: UnifiedRequester, private val client: HttpClient,
private val serializer: KSerializer<T> private val serializer: KSerializer<T>
) : RolesStorage<T>, ) : RolesStorage<T>,
ReadRolesStorage<T> by ReadClientRolesStorage( ReadRolesStorage<T> by ReadClientRolesStorage(
baseUrl, unifiedRequester, serializer baseUrl, client, serializer
), ),
WriteRolesStorage<T> by WriteClientRolesStorage( WriteRolesStorage<T> by WriteClientRolesStorage(
baseUrl, unifiedRequester, serializer baseUrl, client, serializer
) )

View File

@@ -3,13 +3,15 @@ package dev.inmo.postssystem.features.roles.client
import dev.inmo.postssystem.features.roles.common.* import dev.inmo.postssystem.features.roles.common.*
import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
class ReadClientRolesStorage<T : Role>( class ReadClientRolesStorage<T : Role>(
private val baseUrl: String, private val baseUrl: String,
private val unifiedRequester: UnifiedRequester, private val client: HttpClient,
private val serializer: KSerializer<T> private val serializer: KSerializer<T>
) : ReadRolesStorage<T> { ) : ReadRolesStorage<T> {
private val userRolesSerializer = ListSerializer(serializer) private val userRolesSerializer = ListSerializer(serializer)
@@ -21,14 +23,13 @@ class ReadClientRolesStorage<T : Role>(
override suspend fun getSubjects( override suspend fun getSubjects(
role: T role: T
): List<RoleSubject> = unifiedRequester.uniget( ): List<RoleSubject> = client.get(
buildStandardUrl( buildStandardUrl(
userRolesFullUrl, userRolesFullUrl,
usersRolesGetSubjectsPathPart, usersRolesGetSubjectsPathPart,
usersRolesRoleQueryParameterName to unifiedRequester.encodeUrlQueryValue(serializer, role) usersRolesRoleQueryParameterName to role
), )
RoleSubjectsSerializer ).body()
)
override suspend fun getRoles( override suspend fun getRoles(
subject: RoleSubject subject: RoleSubject

View File

@@ -8,7 +8,7 @@ import kotlinx.serialization.builtins.serializer
class WriteClientRolesStorage<T : Role>( class WriteClientRolesStorage<T : Role>(
private val baseUrl: String, private val baseUrl: String,
private val unifiedRequester: UnifiedRequester, private val client: HttpClient,
private val serializer: KSerializer<T> private val serializer: KSerializer<T>
) : WriteRolesStorage<T> { ) : WriteRolesStorage<T> {
private val wrapperSerializer = RolesStorageIncludeExcludeWrapper.serializer( private val wrapperSerializer = RolesStorageIncludeExcludeWrapper.serializer(

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.roles.client"/>

View File

@@ -6,7 +6,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.* import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.* import kotlinx.serialization.json.*
@Serializable(RoleSerializer::class) @Polymorphic
interface Role { interface Role {
companion object { companion object {
fun serializer(): KSerializer<Role> = RoleSerializer fun serializer(): KSerializer<Role> = RoleSerializer

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.roles.common"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.roles.manager.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.roles.manager.common"/>

View File

@@ -1,17 +1,14 @@
package dev.inmo.postssystem.features.roles.manager.server package dev.inmo.postssystem.features.roles.manager.server
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.postssystem.features.roles.common.RolesStorage import dev.inmo.postssystem.features.roles.common.RolesStorage
import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRole import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRole
import dev.inmo.postssystem.features.roles.server.RolesStorageWriteServerRoutesConfigurator import dev.inmo.postssystem.features.roles.server.RolesStorageWriteServerRoutesConfigurator
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
class RolesManagerRolesStorageServerRoutesConfigurator( class RolesManagerRolesStorageServerRoutesConfigurator(
storage: RolesStorage<RolesManagerRole>, storage: RolesStorage<RolesManagerRole>
unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element by RolesStorageWriteServerRoutesConfigurator( ) : ApplicationRoutingConfigurator.Element by RolesStorageWriteServerRoutesConfigurator(
storage, storage,
RolesManagerRole.serializer(), RolesManagerRole.serializer(),
RolesManagerRolesChecker.key, RolesManagerRolesChecker.key
unifiedRouter = unifiedRouter
) )

View File

@@ -12,8 +12,7 @@ class RolesStorageWriteServerRoutesConfigurator<T : Role>(
private val storage: WriteRolesStorage<T>, private val storage: WriteRolesStorage<T>,
private val serializer: KSerializer<T>, private val serializer: KSerializer<T>,
private val includeAuthKey: String, private val includeAuthKey: String,
private val excludeAuthKey: String = includeAuthKey, private val excludeAuthKey: String = includeAuthKey
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
route(usersRolesRootPathPart) { route(usersRolesRootPathPart) {

View File

@@ -3,7 +3,7 @@ package dev.inmo.postssystem.features.roles.server
import dev.inmo.postssystem.features.auth.common.AuthToken import dev.inmo.postssystem.features.auth.common.AuthToken
import dev.inmo.postssystem.features.auth.server.principal import dev.inmo.postssystem.features.auth.server.principal
import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService
import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator import dev.inmo.postssystem.features.common.server.ApplicationAuthenticationConfigurator
import dev.inmo.postssystem.features.roles.common.Role import dev.inmo.postssystem.features.roles.common.Role
import dev.inmo.postssystem.features.roles.common.RolesStorage import dev.inmo.postssystem.features.roles.common.RolesStorage
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode

View File

@@ -11,8 +11,7 @@ import kotlinx.serialization.builtins.serializer
class RolesStorageReadServerRoutesConfigurator<T : Role>( class RolesStorageReadServerRoutesConfigurator<T : Role>(
private val storage: ReadRolesStorage<T>, private val storage: ReadRolesStorage<T>,
private val serializer: KSerializer<T>, private val serializer: KSerializer<T>
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
private val userRolesSerializer = ListSerializer(serializer) private val userRolesSerializer = ListSerializer(serializer)
override fun Route.invoke() { override fun Route.invoke() {

View File

@@ -2,11 +2,9 @@ package dev.inmo.postssystem.features.status.client
import dev.inmo.postssystem.features.status.common.statusAuthorisedPathPart import dev.inmo.postssystem.features.status.common.statusAuthorisedPathPart
import dev.inmo.postssystem.features.status.common.statusRootPart import dev.inmo.postssystem.features.status.common.statusRootPart
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
class StatusFeatureClient( class StatusFeatureClient(

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.status.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.status.common"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.template.client"/>

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.template.common"/>

View File

@@ -5,5 +5,5 @@ import dev.inmo.postssystem.features.auth.client.AuthorizedQualifiers
import dev.inmo.postssystem.features.users.common.ReadUsersStorage import dev.inmo.postssystem.features.users.common.ReadUsersStorage
val loader = AuthorizedModuleLoader { val loader = AuthorizedModuleLoader {
single<ReadUsersStorage> { UsersStorageKtorClient(get(AuthorizedQualifiers.ServerUrlQualifier), get()) } single<ReadUsersStorage> { UsersStorageKtorClient(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get()) }
} }

View File

@@ -1,19 +1,19 @@
package dev.inmo.postssystem.features.users.client package dev.inmo.postssystem.features.users.client
import dev.inmo.postssystem.features.users.common.* import dev.inmo.postssystem.features.users.common.*
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadStandardCrudRepo import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadCRUDRepoClient
import kotlinx.serialization.builtins.nullable import io.ktor.client.*
import io.ktor.http.*
class UsersStorageKtorClient( class UsersStorageKtorClient(
baseUrl: String, baseUrl: String,
unifiedRequester: UnifiedRequester client: HttpClient,
) : ReadUsersStorage, ReadCRUDRepo<User, UserId> by KtorReadStandardCrudRepo( contentType: ContentType
) : ReadUsersStorage, ReadCRUDRepo<User, UserId> by KtorReadCRUDRepoClient(
buildStandardUrl(baseUrl, usersServerPathPart), buildStandardUrl(baseUrl, usersServerPathPart),
unifiedRequester, client,
User.serializer(), contentType,
User.serializer().nullable, { it.long.toString() }
UserId.serializer()
) )

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.users.client"/>

View File

@@ -21,7 +21,3 @@ kotlin {
} }
} }
} }
android {
disableIncludingJvmCodeInAndroidPart()
}

View File

@@ -31,7 +31,7 @@ sealed class User : NewUser {
} }
@Serializable @Serializable
data class DefaultUser( data class RegisteredUser(
override val id: UserId, override val id: UserId,
override val firstName: String, override val firstName: String,
override val lastName: String, override val lastName: String,

View File

@@ -3,8 +3,7 @@ package dev.inmo.postssystem.features.users.common
import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
import dev.inmo.micro_utils.repos.exposed.initTable import dev.inmo.micro_utils.repos.exposed.initTable
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.InsertStatement import org.jetbrains.exposed.sql.statements.*
import org.jetbrains.exposed.sql.statements.UpdateStatement
class ExposedUsersStorage(override val database: Database) : UsersStorage, AbstractExposedCRUDRepo<User, UserId, NewUser>( class ExposedUsersStorage(override val database: Database) : UsersStorage, AbstractExposedCRUDRepo<User, UserId, NewUser>(
tableName = "Users" tableName = "Users"
@@ -15,11 +14,12 @@ class ExposedUsersStorage(override val database: Database) : UsersStorage, Abstr
private val lastNameColumn = text("lastName") private val lastNameColumn = text("lastName")
override val primaryKey: PrimaryKey = PrimaryKey(userIdColumn) override val primaryKey: PrimaryKey = PrimaryKey(userIdColumn)
override val selectById: ISqlExpressionBuilder.(UserId) -> Op<Boolean> = { userIdColumn.eq(it.long) }
override val ResultRow.asId: UserId
get() = UserId(get(userIdColumn))
override val selectByIds: SqlExpressionBuilder.(List<UserId>) -> Op<Boolean> = { userIdColumn.inList(it.map { it.long }) }
override val selectById: SqlExpressionBuilder.(UserId) -> Op<Boolean> = { userIdColumn.eq(it.long) }
override val ResultRow.asObject: User override val ResultRow.asObject: User
get() = DefaultUser( get() = RegisteredUser(
get(userIdColumn).userId, get(userIdColumn).userId,
get(firstNameColumn), get(firstNameColumn),
get(lastNameColumn), get(lastNameColumn),
@@ -30,19 +30,19 @@ class ExposedUsersStorage(override val database: Database) : UsersStorage, Abstr
initTable() initTable()
} }
override fun insert(value: NewUser, it: InsertStatement<Number>) { override fun insert(value: NewUser, it: UpdateBuilder<Int>) {
it[usernameColumn] = value.username.string it[usernameColumn] = value.username.string
it[firstNameColumn] = value.firstName it[firstNameColumn] = value.firstName
it[lastNameColumn] = value.lastName it[lastNameColumn] = value.lastName
} }
override fun update(id: UserId, value: NewUser, it: UpdateStatement) { override fun update(id: UserId?, value: NewUser, it: UpdateBuilder<Int>) {
it[usernameColumn] = value.username.string it[usernameColumn] = value.username.string
it[firstNameColumn] = value.firstName it[firstNameColumn] = value.firstName
it[lastNameColumn] = value.lastName it[lastNameColumn] = value.lastName
} }
override fun InsertStatement<Number>.asObject(value: NewUser): User = DefaultUser( override fun InsertStatement<Number>.asObject(value: NewUser): User = RegisteredUser(
get(userIdColumn).userId, get(userIdColumn).userId,
get(firstNameColumn), get(firstNameColumn),
get(lastNameColumn), get(lastNameColumn),

View File

@@ -1 +0,0 @@
<manifest package="dev.inmo.postssystem.features.users.common"/>

View File

@@ -1,28 +1,21 @@
package dev.inmo.postssystem.features.users.server package dev.inmo.postssystem.features.users.server
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.postssystem.features.users.common.* import dev.inmo.postssystem.features.users.common.*
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadCRUDRepoRoutes
import io.ktor.server.auth.authenticate import io.ktor.server.auth.authenticate
import io.ktor.server.routing.Route import io.ktor.server.routing.Route
import io.ktor.server.routing.route import io.ktor.server.routing.route
import kotlinx.serialization.builtins.nullable
class UsersStorageServerRoutesConfigurator( class UsersStorageServerRoutesConfigurator(
private val usersStorage: ReadUsersStorage, private val usersStorage: ReadUsersStorage
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
authenticate { authenticate {
route(usersServerPathPart) { route(usersServerPathPart) {
configureReadStandardCrudRepoRoutes( configureReadCRUDRepoRoutes(
usersStorage, usersStorage
User.serializer(), ) { UserId(it.toLong()) }
User.serializer().nullable,
UserId.serializer(),
unifiedRouter
)
} }
} }
} }

View File

@@ -1,39 +1,42 @@
[versions] [versions]
kotlin = "1.6.21" kotlin = "2.0.10"
kotlin-serialization = "1.3.3" kotlin-serialization = "1.7.1"
jsuikit = "0.1.1" kotlin-coroutines = "1.8.1"
compose = "1.2.0-alpha01-dev686" jsuikit = "0.7.6"
microutils = "0.10.4" compose = "1.7.0-alpha02"
tgbotapi = "1.1.1" microutils = "0.22.0"
ktor = "2.0.1" tgbotapi = "17.0.0"
klock = "2.7.0" ktor = "2.3.11"
koin = "3.2.0" korlibs = "5.4.0"
exposed = "0.38.2" koin = "3.5.6"
psql = "42.3.0" exposed = "0.53.0"
scrimage = "4.0.31" psql = "42.3.6"
dokka = "1.6.21" scrimage = "4.1.1"
dokka = "1.9.20"
logback = "1.2.10" logback = "1.2.10"
uuid = "0.4.0" uuid = "0.8.4"
android-junit = "4.12" android-junit = "4.12"
android-test-junit = "1.1.2" android-test-junit = "1.1.2"
android-espresso-core = "3.3.0" android-espresso-core = "3.3.0"
gh-release = "2.3.7" gh-release = "2.5.1"
android-gradle = "7.0.4" android-gradle = "8.2.2"
dexcount = "3.1.0" dexcount = "3.1.0"
android-coreKtx = "1.7.0" android-coreKtx = "1.12.0"
android-recyclerView = "1.2.1" android-recyclerView = "1.2.1"
android-appCompat = "1.4.1" android-appCompat = "1.4.1"
android-fragment = "1.6.2"
android-compose-material3 = "1.1.2"
android-espresso = "3.3.0" android-espresso = "3.3.0"
android-test = "1.1.2" android-test = "1.1.2"
android-props-minSdk = "19" android-props-minSdk = "21"
android-props-compileSdk = "32" android-props-compileSdk = "35"
android-props-buildTools = "32.0.0" android-props-buildTools = "35.0.0"
[libraries] [libraries]
@@ -42,6 +45,10 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref =
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin-serialization" } kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin-serialization" }
kotlin-serialization-properties = { module = "org.jetbrains.kotlinx:kotlinx-serialization-properties", version.ref = "kotlin-serialization" } kotlin-serialization-properties = { module = "org.jetbrains.kotlinx:kotlinx-serialization-properties", version.ref = "kotlin-serialization" }
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
kotlin-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlin-coroutines" }
kotlin-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlin-coroutines" }
jsuikit = { module = "dev.inmo:kjsuikit", version.ref = "jsuikit" } jsuikit = { module = "dev.inmo:kjsuikit", version.ref = "jsuikit" }
postgresql = { module = "org.postgresql:postgresql", version.ref = "psql" } postgresql = { module = "org.postgresql:postgresql", version.ref = "psql" }
@@ -81,12 +88,18 @@ microutils-serialization-typedserializer = { module = "dev.inmo:micro_utils.seri
tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" } tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
klock = { module = "com.soywiz.korlibs.klock:klock", version.ref = "klock" } klock = { module = "com.soywiz.korge:korlibs-time", version.ref = "korlibs" }
krypto = { module = "com.soywiz.korge:korlibs-crypto", version.ref = "korlibs" }
scrimage = { module = "com.sksamuel.scrimage:scrimage-core", version.ref = "scrimage" } scrimage = { module = "com.sksamuel.scrimage:scrimage-core", version.ref = "scrimage" }
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "android-test-junit" } android-coreKtx = { module = "androidx.core:core-ktx", version.ref = "android-coreKtx" }
androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "android-espresso-core" } android-recyclerView = { module = "androidx.recyclerview:recyclerview", version.ref = "android-recyclerView" }
android-appCompat-resources = { module = "androidx.appcompat:appcompat-resources", version.ref = "android-appCompat" }
android-compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "android-compose-material3" }
android-fragment = { module = "androidx.fragment:fragment", version.ref = "android-fragment" }
android-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "android-espresso" }
android-test-junit = { module = "androidx.test.ext:junit", version.ref = "android-test" }
# classpaths # classpaths
@@ -100,3 +113,4 @@ buildscript-android-dexcount = { module = "com.getkeepsafe.dexcount:dexcount-gra
[plugins] [plugins]
compose = { id = "org.jetbrains.compose", version.ref = "compose" } compose = { id = "org.jetbrains.compose", version.ref = "compose" }
kt-jb-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

View File

@@ -1,4 +1,4 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,11 +1,16 @@
project.version = "$version" project.version = "$version"
project.group = "$group" project.group = "$group"
// apply from: "$publishGradlePath" apply from: "$publishGradlePath"
kotlin { kotlin {
android { androidTarget {
publishAllLibraryVariants() publishAllLibraryVariants()
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
} }
sourceSets { sourceSets {
@@ -18,18 +23,15 @@ kotlin {
dependencies { dependencies {
implementation kotlin('test-common') implementation kotlin('test-common')
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
} implementation libs.kt.coroutines.test
}
androidTest {
dependencies {
implementation kotlin('test-junit')
implementation libs.androidx.test.junit
implementation libs.androidx.espresso
} }
} }
} }
allTargetsConfiguration()
} }
apply from: "$defaultAndroidSettingsPresetPath" apply from: "$defaultAndroidSettingsPresetPath"
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

View File

@@ -4,7 +4,13 @@ project.group = "$group"
apply from: "$publishGradlePath" apply from: "$publishGradlePath"
kotlin { kotlin {
jvm() jvm {
compilations.main {
kotlinOptions {
jvmTarget = "17"
}
}
}
sourceSets { sourceSets {
commonMain { commonMain {
@@ -16,6 +22,7 @@ kotlin {
dependencies { dependencies {
implementation kotlin('test-common') implementation kotlin('test-common')
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
implementation libs.kotlin.coroutines.test
} }
} }
@@ -25,11 +32,9 @@ kotlin {
} }
} }
} }
allTargetsConfiguration()
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }

View File

@@ -13,21 +13,25 @@ kotlin {
commonMain { commonMain {
dependencies { dependencies {
implementation kotlin('stdlib') implementation kotlin('stdlib')
api libs.kotlin.serialization
} }
} }
commonTest { commonTest {
dependencies { dependencies {
implementation kotlin('test-common') implementation kotlin('test-common')
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
implementation libs.kotlin.coroutines.test
} }
} }
jsTest { jsTest {
dependencies { dependencies {
implementation kotlin('test-js') implementation kotlin('test-js')
implementation kotlin('test-junit')
} }
} }
} }
}
allTargetsConfiguration()
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
} }

View File

@@ -4,19 +4,30 @@ project.group = "$group"
apply from: "$publishGradlePath" apply from: "$publishGradlePath"
kotlin { kotlin {
jvm() jvm {
compilations.main {
kotlinOptions {
jvmTarget = "17"
}
}
}
js (IR) { js (IR) {
browser() browser()
nodejs() nodejs()
} }
android { androidTarget {
publishAllLibraryVariants() publishAllLibraryVariants()
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
} }
sourceSets { sourceSets {
commonMain { commonMain {
dependencies { dependencies {
implementation libs.kotlin.std implementation kotlin('stdlib')
api libs.kotlin.serialization api libs.kotlin.serialization
} }
} }
@@ -24,6 +35,7 @@ kotlin {
dependencies { dependencies {
implementation kotlin('test-common') implementation kotlin('test-common')
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
implementation libs.kotlin.coroutines.test
} }
} }
jvmTest { jvmTest {
@@ -34,24 +46,23 @@ kotlin {
jsTest { jsTest {
dependencies { dependencies {
implementation kotlin('test-js') implementation kotlin('test-js')
implementation kotlin('test-junit')
} }
} }
androidTest { androidUnitTest {
dependencies { dependencies {
implementation kotlin('test-junit') implementation kotlin('test-junit')
implementation libs.androidx.test.junit implementation libs.android.test.junit
implementation libs.androidx.espresso implementation libs.android.espresso
} }
} }
}
allTargetsConfiguration() androidMain.dependsOn jvmMain
}
} }
apply from: "$defaultAndroidSettingsPresetPath" apply from: "$defaultAndroidSettingsPresetPath"
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }

Some files were not shown because too many files have changed in this diff Show More