Compare commits
10 Commits
0f983d9286
...
reborn/2
| Author | SHA1 | Date | |
|---|---|---|---|
| 546736690c | |||
| e98a484c4d | |||
| ff973e63fc | |||
| 399405a4fb | |||
| b7e5e2745d | |||
| 92cd98b80f | |||
| b73df49925 | |||
| f835dc1557 | |||
| 5bbe0b8a0e | |||
| 9216c013ec |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.idea
|
||||
.kotlin
|
||||
out/*
|
||||
*.iml
|
||||
target
|
||||
|
||||
14
README.md
14
README.md
@@ -1,12 +1,14 @@
|
||||
## Структура проекта
|
||||
|
||||
* **Features** - набор **законченных** фич проекта. Считается, что любая фича, находящаяся в мастере может быть добавлена в
|
||||
клиент и использована в нем. Исключением является `common` - это набор вещей, используемых везде. В подпунктах представлены
|
||||
части, на которые *обычно* разделяется фича
|
||||
* Common - общая для фичи часть. Тут, как правило, хранятся конвенции путей для сетевых соединений, общие типы и пр.
|
||||
* Server - часть, включаемая в сервер для подключения фичи. Обычно содержит работу с бд, определение модулей сервера и пр.
|
||||
* Client - часть с клиентским кодом. В большинстве своём включает работу с сервером, MVVM часть (View при этом должны
|
||||
находиться в платформенной части, если их нельзя вынести в сommon часть клиента)
|
||||
клиент и использована в нем. Исключением является `common` - это набор вещей, используемых везде.
|
||||
* Части, на которые *обычно* разделяется фича
|
||||
* Common - общая для фичи часть. Тут, как правило, хранятся конвенции путей для сетевых соединений, общие типы и пр.
|
||||
* Server - часть, включаемая в сервер для подключения фичи. Обычно содержит работу с бд, определение модулей сервера и пр.
|
||||
* Client - часть с клиентским кодом. В большинстве своём включает работу с сервером, MVVM часть (View при этом должны
|
||||
находиться в платформенной части, если их нельзя вынести в сommon часть клиента)
|
||||
* Также существует фича `client`, которая не является фичей самой по-себе. Фактически, это набор разных фич, который системно
|
||||
отсутствуют в бэке и используются в основном для пробрасывания удобных `API` и `View` для клиента
|
||||
* **Services** - модули, отвечающие за клиент-серверную работу фич с точки зрения их взаимодействия. Например, в рамках сервисов
|
||||
должен быть добавлен модуль для постов - именно через сервисы будет происходить создание поста, его редактирование и удаление
|
||||
* **Client** - итоговый клиент. На момент написания этой доки (`Пн окт 25 12:56:41 +06 2021`) предполагается два варианта:
|
||||
|
||||
@@ -23,6 +23,7 @@ allprojects {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
|
||||
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -8,7 +8,6 @@ import dev.inmo.postssystem.features.auth.client.ui.*
|
||||
import dev.inmo.postssystem.features.common.common.baseKoin
|
||||
import dev.inmo.postssystem.features.common.common.getAllDistinct
|
||||
import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMHandler
|
||||
import dev.inmo.postssystem.features.common.common.ui.fsm.UIFSMStateSerializer
|
||||
import dev.inmo.postssystem.services.posts.client.ui.list.PostsListUIFSMState
|
||||
import dev.inmo.postssystem.services.posts.client.ui.list.PostsListUIState
|
||||
import kotlinx.browser.*
|
||||
@@ -29,8 +28,7 @@ val defaultTypedSerializer = TypedSerializer<Any>(
|
||||
"Short" to Short.serializer(),
|
||||
"Byte" to Byte.serializer(),
|
||||
"Float" to Float.serializer(),
|
||||
"Double" to Double.serializer(),
|
||||
"UIFSMState" to UIFSMStateSerializer
|
||||
"Double" to Double.serializer()
|
||||
)
|
||||
val defaultSerialFormat = Json {
|
||||
ignoreUnknownKeys = true
|
||||
|
||||
@@ -58,5 +58,6 @@
|
||||
"semver": "^7.3.2",
|
||||
"svgo": "^2.8.0",
|
||||
"watch-run": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
|
||||
}
|
||||
|
||||
@@ -1,39 +1,16 @@
|
||||
apply plugin: 'com.getkeepsafe.dexcount'
|
||||
|
||||
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()
|
||||
buildToolsVersion libs.versions.android.props.buildTools.get()
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion libs.versions.android.props.minSdk.get().toInteger()
|
||||
compileSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
|
||||
targetSdkVersion libs.versions.android.props.compileSdk.get().toInteger()
|
||||
versionCode "${android_code_version}".toInteger()
|
||||
versionName "$version"
|
||||
namespace "${project.group}.${project.name}"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -51,18 +28,7 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -13,21 +13,6 @@ allprojects {
|
||||
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"
|
||||
mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
|
||||
mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
|
||||
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.inmo.postssystem.features.auth.client
|
||||
|
||||
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.AuthTokenInfo
|
||||
import dev.inmo.postssystem.features.common.common.AdditionalModules
|
||||
@@ -27,7 +26,6 @@ fun createAuthorizedFeaturesDIModule(
|
||||
installClientAuthenticator(serverUrl, get(), get(AuthorizedQualifiers.CredsQualifier), onAuthKeyUpdated, onUserRetrieved, onAuthKeyInvalidated)
|
||||
}
|
||||
}
|
||||
single { UnifiedRequester(get(), get()) }
|
||||
single { StatusFeatureClient(get(AuthorizedQualifiers.ServerUrlQualifier), get()) }
|
||||
|
||||
AdditionalModules.Authorized.modules.forEach {
|
||||
|
||||
@@ -2,14 +2,14 @@ package dev.inmo.postssystem.features.auth.client
|
||||
|
||||
import dev.inmo.postssystem.features.auth.common.*
|
||||
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 io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.*
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
|
||||
class ClientAuthFeature(
|
||||
private val requester: UnifiedRequester,
|
||||
private val client: HttpClient,
|
||||
baseUrl: String
|
||||
) : AuthFeature {
|
||||
private val rootUrl = buildStandardUrl(baseUrl.dropLastWhile { it == '/' }, authRootPathPart)
|
||||
@@ -26,28 +26,23 @@ class ClientAuthFeature(
|
||||
authGetMePathPart
|
||||
)
|
||||
|
||||
constructor(client: HttpClient, rootUrl: String): this(
|
||||
UnifiedRequester(client),
|
||||
rootUrl
|
||||
)
|
||||
override suspend fun auth(creds: AuthCreds): AuthTokenInfo? = client.post(
|
||||
fullAuthPath
|
||||
) {
|
||||
setBody(creds)
|
||||
}.bodyOrNull()
|
||||
|
||||
override suspend fun auth(creds: AuthCreds): AuthTokenInfo? = requester.unipost(
|
||||
fullAuthPath,
|
||||
AuthCreds.serializer() to creds,
|
||||
AuthTokenInfo.serializer().nullable
|
||||
)
|
||||
override suspend fun refresh(refresh: RefreshToken): AuthTokenInfo? = client.post(
|
||||
fullRefreshPath
|
||||
) {
|
||||
setBody(refresh)
|
||||
}.bodyOrNull()
|
||||
|
||||
override suspend fun refresh(refresh: RefreshToken): AuthTokenInfo? = requester.unipost(
|
||||
fullRefreshPath,
|
||||
RefreshToken.serializer() to refresh,
|
||||
AuthTokenInfo.serializer().nullable
|
||||
)
|
||||
|
||||
override suspend fun getMe(authToken: AuthToken): User? = requester.unipost(
|
||||
fullGetMePath,
|
||||
AuthToken.serializer() to authToken,
|
||||
User.serializer().nullable
|
||||
)
|
||||
override suspend fun getMe(authToken: AuthToken): User? = client.post(
|
||||
fullGetMePath
|
||||
) {
|
||||
setBody(authToken)
|
||||
}.bodyOrNull()
|
||||
|
||||
fun isAuthRequest(builder: HttpRequestBuilder): Boolean = builder.url.buildString().let {
|
||||
it == fullAuthPath || it == fullRefreshPath
|
||||
|
||||
@@ -37,7 +37,7 @@ fun HttpClientConfig<*>.installClientAuthenticator(
|
||||
}.onSecond {
|
||||
currentRefreshToken = it.refresh
|
||||
}
|
||||
val creds = initialAuthKey.t1 as? AuthCreds
|
||||
val creds = initialAuthKey.t1OrNull as? AuthCreds
|
||||
var userRefreshJob: Job? = null
|
||||
|
||||
install("Auth Token Refresher") {
|
||||
|
||||
@@ -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.ui.fsm.UIFSMExceptionHandler
|
||||
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()) }
|
||||
|
||||
singleWithRandomQualifier {
|
||||
|
||||
@@ -4,9 +4,9 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed interface AuthUIError {
|
||||
@Serializable
|
||||
// @Serializable
|
||||
object ServerUnavailable : AuthUIError
|
||||
@Serializable
|
||||
// @Serializable
|
||||
object AuthIncorrect : AuthUIError
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ sealed interface AuthUIError {
|
||||
sealed interface AuthUIState {
|
||||
@Serializable
|
||||
data class Init(val showError: AuthUIError? = null) : AuthUIState
|
||||
@Serializable
|
||||
// @Serializable
|
||||
object Loading : AuthUIState
|
||||
@Serializable
|
||||
// @Serializable
|
||||
object Authorized : AuthUIState
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -29,7 +29,7 @@ val loader = DefaultModuleLoader {
|
||||
strictlyOn(get<AuthView>())
|
||||
}
|
||||
}
|
||||
}
|
||||
} + CommonAuthModuleLoader()
|
||||
|
||||
class AuthView(
|
||||
private val viewModel: AuthUIViewModel,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.auth.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.auth.common"/>
|
||||
@@ -2,7 +2,7 @@ package dev.inmo.postssystem.features.auth.server
|
||||
|
||||
import dev.inmo.postssystem.features.auth.common.*
|
||||
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.micro_utils.coroutines.safely
|
||||
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.server.application.call
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.request.receive
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.sessions.sessions
|
||||
@@ -24,84 +25,72 @@ fun User.principal() = AuthUserPrincipal(this)
|
||||
|
||||
class AuthenticationRoutingConfigurator(
|
||||
private val authFeature: AuthFeature,
|
||||
private val authTokensService: AuthTokensService,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
private val authTokensService: AuthTokensService
|
||||
) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element {
|
||||
override fun Route.invoke() {
|
||||
unifiedRouter.apply {
|
||||
route(authRootPathPart) {
|
||||
post(authAuthPathPart) {
|
||||
safely(
|
||||
{
|
||||
// TODO:: add error info
|
||||
it.printStackTrace()
|
||||
call.respond(
|
||||
HttpStatusCode.InternalServerError,
|
||||
"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())
|
||||
)
|
||||
route(authRootPathPart) {
|
||||
post(authAuthPathPart) {
|
||||
safely(
|
||||
{
|
||||
// TODO:: add error info
|
||||
it.printStackTrace()
|
||||
call.respond(
|
||||
HttpStatusCode.InternalServerError,
|
||||
"Something went wrong"
|
||||
)
|
||||
}
|
||||
) {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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.RefreshToken
|
||||
import dev.inmo.postssystem.features.users.common.UserId
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.postssystem.features.auth.server.tokens
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.milliseconds
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.milliseconds
|
||||
import dev.inmo.postssystem.features.auth.common.*
|
||||
import dev.inmo.postssystem.features.common.common.Milliseconds
|
||||
import dev.inmo.postssystem.features.users.common.*
|
||||
|
||||
18
features/client/template/client/build.gradle
Normal file
18
features/client/template/client/build.gradle
Normal 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
features/client/template/common/build.gradle
Normal file
17
features/client/template/common/build.gradle
Normal 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
features/client/template/server/build.gradle
Normal file
17
features/client/template/server/build.gradle
Normal 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -49,12 +49,16 @@ fun baseKoin(
|
||||
single { repoFactory() }
|
||||
single { defaultScope }
|
||||
single(DefaultQualifiers.UIScopeQualifier) { get<CoroutineScope>().LinkedSupervisorScope(Dispatchers.Main) }
|
||||
single<StatesMachine<UIFSMState>>(UIFSMQualifier) { UIFSM(get()) { (this@single to this@UIFSM).apply(get(
|
||||
DefaultQualifiers.FSMHandlersBuilderQualifier
|
||||
)) } }
|
||||
|
||||
AdditionalModules.Default.modules.forEach {
|
||||
it.apply { load() }
|
||||
single<StatesMachine<UIFSMState>>(DefaultQualifiers.UIFSMQualifier) {
|
||||
UIFSM(get()) {
|
||||
(this@single to this@UIFSM).apply(get(DefaultQualifiers.FSMHandlersBuilderQualifier))
|
||||
}
|
||||
}
|
||||
} + AdditionalModules.Default.modules.map {
|
||||
module {
|
||||
with(it) {
|
||||
load()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -6,5 +6,5 @@ object DefaultQualifiers {
|
||||
val SettingsQualifier = StringQualifier("Settings")
|
||||
val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder")
|
||||
val UIScopeQualifier = StringQualifier("CoroutineScopeUI")
|
||||
val UIFSMQualifier = StringQualifier("FSM")
|
||||
val UIFSMQualifier = StringQualifier("UIFSM")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
val newModuleLoader = ModuleLoader.ByCallback(loadingBlock)
|
||||
AdditionalModules.Default.addModule(newModuleLoader)
|
||||
|
||||
@@ -6,8 +6,6 @@ import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
|
||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo
|
||||
import org.koin.core.qualifier.StringQualifier
|
||||
|
||||
val UIFSMQualifier = StringQualifier("UIFSM")
|
||||
|
||||
fun UIFSM(
|
||||
repo: DefaultStatesManagerRepo<UIFSMState>,
|
||||
handlersSetter: FSMBuilder<UIFSMState>.() -> Unit
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.ISO8601
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.ISO8601
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
|
||||
object DateTimeView {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.common.client"/>
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.filesize
|
||||
import io.ktor.utils.io.core.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.ByteArraySerializer
|
||||
@@ -27,9 +28,18 @@ class BytesBasedInputProvider(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable(SimpleInputProviderSerializer::class)
|
||||
expect class FileBasedInputProvider : SimpleInputProvider {
|
||||
internal interface FileInputProvider : SimpleInputProvider {
|
||||
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)
|
||||
|
||||
@@ -7,12 +7,9 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable(SimpleInputProviderSerializer::class)
|
||||
actual class FileBasedInputProvider internal constructor(
|
||||
actual val file: MPPFile
|
||||
) : SimpleInputProvider {
|
||||
override val contentBytes: Long
|
||||
get() = file.filesize
|
||||
|
||||
override fun invoke(): Input = error("Files inputs must not be used directly")
|
||||
actual override val file: MPPFile
|
||||
) : FileInputProvider {
|
||||
actual override fun invoke(): Input = error("Files inputs must not be used directly")
|
||||
}
|
||||
|
||||
fun MPPFile.inputProvider() = FileBasedInputProvider(this)
|
||||
|
||||
@@ -8,10 +8,8 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable(SimpleInputProviderSerializer::class)
|
||||
actual class FileBasedInputProvider(
|
||||
actual val file: MPPFile
|
||||
) : SimpleInputProvider {
|
||||
override val contentBytes: Long?
|
||||
get() = file.filesize
|
||||
actual override val file: MPPFile
|
||||
) : FileInputProvider {
|
||||
|
||||
override fun invoke(): Input = file.inputStream().asInput()
|
||||
actual override fun invoke(): Input = file.inputStream().asInput()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import org.koin.core.definition.Definition
|
||||
import org.koin.core.definition.KoinDefinition
|
||||
import org.koin.core.instance.InstanceFactory
|
||||
import org.koin.core.module.Module
|
||||
import org.koin.core.qualifier.Qualifier
|
||||
@@ -11,6 +12,6 @@ inline fun <reified T : Any> Module.singleWithBinds(
|
||||
qualifier: Qualifier? = null,
|
||||
createdAtStart: Boolean = false,
|
||||
noinline definition: Definition<T>
|
||||
): Pair<Module, InstanceFactory<*>> {
|
||||
): KoinDefinition<*> {
|
||||
return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.common.common"/>
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 io.ktor.server.application.Application
|
||||
@@ -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
|
||||
|
||||
object Qualifiers {
|
||||
val filesFolderQualifier = StringQualifier("filesFolder")
|
||||
val commonFilesFolderQualifier = StringQualifier("commonFilesFolder")
|
||||
val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory")
|
||||
}
|
||||
@@ -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 org.koin.core.module.Module
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.binary.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.binary.common"/>
|
||||
@@ -3,8 +3,8 @@ package dev.inmo.postssystem.features.content.binary.server
|
||||
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
|
||||
import dev.inmo.postssystem.features.common.common.singleWithBinds
|
||||
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
|
||||
import dev.inmo.postssystem.features.common.server.sessions.Qualifiers
|
||||
import dev.inmo.postssystem.features.common.server.sessions.ServerModuleLoader
|
||||
import dev.inmo.postssystem.features.common.server.Qualifiers
|
||||
import dev.inmo.postssystem.features.common.server.ServerModuleLoader
|
||||
import dev.inmo.postssystem.features.content.common.BinaryContent
|
||||
import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper
|
||||
import dev.inmo.postssystem.features.files.common.*
|
||||
|
||||
@@ -6,7 +6,6 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.mime_types.KnownMimeTypes
|
||||
import dev.inmo.micro_utils.pagination.*
|
||||
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.server.storage.ServerContentStorage
|
||||
import dev.inmo.postssystem.features.files.common.*
|
||||
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.client"/>
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.inmo.postssystem.features.content.common
|
||||
|
||||
import dev.inmo.micro_utils.common.FileName
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.*
|
||||
import dev.inmo.micro_utils.mime_types.MimeType
|
||||
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
|
||||
import kotlinx.serialization.PolymorphicSerializer
|
||||
@@ -30,6 +29,18 @@ data class BinaryContent(
|
||||
) : Content
|
||||
|
||||
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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.common"/>
|
||||
@@ -3,6 +3,7 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kt.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.content.text.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.content.content.text.common"/>
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.postssystem.features.content.text.server
|
||||
|
||||
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.server.ServerContentStorageWrapper
|
||||
import dev.inmo.postssystem.features.content.text.common.TextContent
|
||||
|
||||
@@ -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.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.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.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.readBytes
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.encodeURLQueryComponent
|
||||
import kotlinx.serialization.BinaryFormat
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
|
||||
class ClientReadFilesStorage(
|
||||
baseUrl: String,
|
||||
private val client: HttpClient,
|
||||
private val serialFormat: BinaryFormat
|
||||
) : ReadFilesStorage, ReadCRUDRepo<MetaFileInfoStorageWrapper, FileId> by KtorReadStandardCrudRepo(
|
||||
private val serialFormat: BinaryFormat,
|
||||
contentType: ContentType
|
||||
) : ReadFilesStorage, ReadCRUDRepo<MetaFileInfoStorageWrapper, FileId> by KtorReadCRUDRepoClient<MetaFileInfoStorageWrapper, FileId>(
|
||||
buildStandardUrl(baseUrl, filesRootPathPart),
|
||||
UnifiedRequester(client, serialFormat),
|
||||
MetaFileInfoStorageWrapper.serializer(),
|
||||
MetaFileInfoStorageWrapper.serializer().nullable,
|
||||
FileId.serializer()
|
||||
client,
|
||||
contentType,
|
||||
{ it.string.encodeURLQueryComponent() }
|
||||
) {
|
||||
private val unifiedRequester = UnifiedRequester(client, serialFormat)
|
||||
private val fullFilesPath = buildStandardUrl(baseUrl, filesRootPathPart)
|
||||
private val fullFilesGetBytesPath = buildStandardUrl(
|
||||
fullFilesPath,
|
||||
@@ -38,12 +37,11 @@ class ClientReadFilesStorage(
|
||||
|
||||
override suspend fun getFullFileInfo(
|
||||
id: FileId
|
||||
): FullFileInfoStorageWrapper? = unifiedRequester.uniget(
|
||||
): FullFileInfoStorageWrapper? = client.get(
|
||||
buildStandardUrl(
|
||||
fullFilesPath,
|
||||
filesGetFullFileInfoPathPart,
|
||||
filesFileIdParameter to unifiedRequester.encodeUrlQueryValue(FileId.serializer(), id)
|
||||
),
|
||||
FullFileInfoStorageWrapper.serializer().nullable
|
||||
)
|
||||
filesFileIdParameter to id.string.encodeURLQueryComponent()
|
||||
)
|
||||
).bodyOrNull()
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ import dev.inmo.postssystem.features.auth.client.AuthorizedQualifiers
|
||||
import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage
|
||||
|
||||
val loader = AuthorizedModuleLoader {
|
||||
single<ReadFilesStorage> { ClientReadFilesStorage(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get()) }
|
||||
single<ReadFilesStorage> { ClientReadFilesStorage(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get(), get()) }
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.files.client"/>
|
||||
@@ -61,4 +61,8 @@ class DiskReadFilesStorage(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getIdsByPagination(pagination: Pagination): PaginationResult<FileId> {
|
||||
return metasKeyValueRepo.keys(pagination)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.files.common"/>
|
||||
@@ -4,10 +4,13 @@ import dev.inmo.postssystem.features.files.common.*
|
||||
import dev.inmo.postssystem.features.files.common.storage.*
|
||||
import dev.inmo.micro_utils.ktor.server.*
|
||||
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.configureWriteStandardCrudRepoRoutes
|
||||
import dev.inmo.micro_utils.repos.ktor.server.crud.*
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.decodeURLQueryComponent
|
||||
import io.ktor.server.application.call
|
||||
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.routing.*
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
@@ -15,47 +18,33 @@ import kotlinx.serialization.builtins.nullable
|
||||
class FilesRoutingConfigurator(
|
||||
private val filesStorage: ReadFilesStorage,
|
||||
private val writeFilesStorage: WriteFilesStorage?,
|
||||
private val unifierRouter: UnifiedRouter
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
constructor(filesStorage: FilesStorage, unifierRouter: UnifiedRouter) : this(filesStorage, filesStorage, unifierRouter)
|
||||
constructor(filesStorage: FilesStorage) : this(filesStorage, filesStorage)
|
||||
|
||||
override fun Route.invoke() {
|
||||
authenticate {
|
||||
route(filesRootPathPart) {
|
||||
configureReadStandardCrudRepoRoutes(
|
||||
configureReadCRUDRepoRoutes(
|
||||
filesStorage,
|
||||
MetaFileInfoStorageWrapper.serializer(),
|
||||
MetaFileInfoStorageWrapper.serializer().nullable,
|
||||
FileId.serializer(),
|
||||
unifierRouter
|
||||
::FileId
|
||||
)
|
||||
writeFilesStorage ?.let {
|
||||
configureWriteStandardCrudRepoRoutes(
|
||||
writeFilesStorage,
|
||||
FullFileInfoStorageWrapper.serializer(),
|
||||
FullFileInfoStorageWrapper.serializer().nullable,
|
||||
FullFileInfo.serializer(),
|
||||
FileId.serializer(),
|
||||
unifierRouter
|
||||
)
|
||||
configureWriteCRUDRepoRoutes(writeFilesStorage)
|
||||
}
|
||||
|
||||
unifierRouter.apply {
|
||||
post(filesGetFilesPathPart) {
|
||||
call.respondBytes(
|
||||
filesStorage.getBytes(
|
||||
uniload(FileId.serializer())
|
||||
)
|
||||
post(filesGetFilesPathPart) {
|
||||
call.respondBytes(
|
||||
filesStorage.getBytes(
|
||||
call.receive()
|
||||
)
|
||||
}
|
||||
get(filesGetFullFileInfoPathPart) {
|
||||
unianswer(
|
||||
FullFileInfoStorageWrapper.serializer().nullable,
|
||||
filesStorage.getFullFileInfo(
|
||||
decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
get(filesGetFullFileInfoPathPart) {
|
||||
call.respond(
|
||||
filesStorage.getFullFileInfo(
|
||||
FileId(call.getParameterOrSendError(filesFileIdParameter) ?.decodeURLQueryComponent() ?: return@get)
|
||||
) ?: HttpStatusCode.NoContent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.posts.client"/>
|
||||
@@ -1,6 +1,6 @@
|
||||
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.content.common.Content
|
||||
import dev.inmo.postssystem.features.content.common.ContentId
|
||||
@@ -25,8 +25,8 @@ typealias ContentIds = List<ContentId>
|
||||
* @see RegisteredPost
|
||||
*/
|
||||
@Serializable
|
||||
sealed class Post {
|
||||
abstract val content: ContentIds
|
||||
sealed interface Post {
|
||||
val content: ContentIds
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ sealed class Post {
|
||||
@Serializable
|
||||
data class NewPost(
|
||||
override val content: ContentIds
|
||||
) : Post()
|
||||
) : Post
|
||||
|
||||
/**
|
||||
* Registered [Post]
|
||||
@@ -46,12 +46,12 @@ data class RegisteredPost(
|
||||
override val content: ContentIds,
|
||||
@Serializable(DateTimeSerializer::class)
|
||||
val creationDate: DateTime
|
||||
) : Post()
|
||||
) : Post
|
||||
|
||||
@Serializable
|
||||
data class PostWithContent(
|
||||
val post: Post,
|
||||
val content: List<Content>
|
||||
val content: List<@Polymorphic Content>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.posts.common"/>
|
||||
@@ -1,6 +1,6 @@
|
||||
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.postssystem.features.content.common.ContentId
|
||||
import dev.inmo.postssystem.features.posts.common.*
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.publication.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.publication.common"/>
|
||||
@@ -1,17 +1,17 @@
|
||||
package dev.inmo.postssystem.features.roles.client
|
||||
|
||||
import dev.inmo.postssystem.features.roles.common.*
|
||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
||||
import io.ktor.client.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
|
||||
class ClientRolesStorage<T : Role>(
|
||||
private val baseUrl: String,
|
||||
private val unifiedRequester: UnifiedRequester,
|
||||
private val client: HttpClient,
|
||||
private val serializer: KSerializer<T>
|
||||
) : RolesStorage<T>,
|
||||
ReadRolesStorage<T> by ReadClientRolesStorage(
|
||||
baseUrl, unifiedRequester, serializer
|
||||
baseUrl, client, serializer
|
||||
),
|
||||
WriteRolesStorage<T> by WriteClientRolesStorage(
|
||||
baseUrl, unifiedRequester, serializer
|
||||
baseUrl, client, serializer
|
||||
)
|
||||
|
||||
@@ -3,13 +3,15 @@ package dev.inmo.postssystem.features.roles.client
|
||||
import dev.inmo.postssystem.features.roles.common.*
|
||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
||||
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.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class ReadClientRolesStorage<T : Role>(
|
||||
private val baseUrl: String,
|
||||
private val unifiedRequester: UnifiedRequester,
|
||||
private val client: HttpClient,
|
||||
private val serializer: KSerializer<T>
|
||||
) : ReadRolesStorage<T> {
|
||||
private val userRolesSerializer = ListSerializer(serializer)
|
||||
@@ -21,14 +23,13 @@ class ReadClientRolesStorage<T : Role>(
|
||||
|
||||
override suspend fun getSubjects(
|
||||
role: T
|
||||
): List<RoleSubject> = unifiedRequester.uniget(
|
||||
): List<RoleSubject> = client.get(
|
||||
buildStandardUrl(
|
||||
userRolesFullUrl,
|
||||
usersRolesGetSubjectsPathPart,
|
||||
usersRolesRoleQueryParameterName to unifiedRequester.encodeUrlQueryValue(serializer, role)
|
||||
),
|
||||
RoleSubjectsSerializer
|
||||
)
|
||||
usersRolesRoleQueryParameterName to role
|
||||
)
|
||||
).body()
|
||||
|
||||
override suspend fun getRoles(
|
||||
subject: RoleSubject
|
||||
|
||||
@@ -8,7 +8,7 @@ import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class WriteClientRolesStorage<T : Role>(
|
||||
private val baseUrl: String,
|
||||
private val unifiedRequester: UnifiedRequester,
|
||||
private val client: HttpClient,
|
||||
private val serializer: KSerializer<T>
|
||||
) : WriteRolesStorage<T> {
|
||||
private val wrapperSerializer = RolesStorageIncludeExcludeWrapper.serializer(
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.roles.client"/>
|
||||
@@ -6,7 +6,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.*
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
@Serializable(RoleSerializer::class)
|
||||
@Polymorphic
|
||||
interface Role {
|
||||
companion object {
|
||||
fun serializer(): KSerializer<Role> = RoleSerializer
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.roles.common"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.roles.manager.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.roles.manager.common"/>
|
||||
@@ -1,17 +1,14 @@
|
||||
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.manager.common.RolesManagerRole
|
||||
import dev.inmo.postssystem.features.roles.server.RolesStorageWriteServerRoutesConfigurator
|
||||
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
|
||||
|
||||
class RolesManagerRolesStorageServerRoutesConfigurator(
|
||||
storage: RolesStorage<RolesManagerRole>,
|
||||
unifiedRouter: UnifiedRouter
|
||||
storage: RolesStorage<RolesManagerRole>
|
||||
) : ApplicationRoutingConfigurator.Element by RolesStorageWriteServerRoutesConfigurator(
|
||||
storage,
|
||||
RolesManagerRole.serializer(),
|
||||
RolesManagerRolesChecker.key,
|
||||
unifiedRouter = unifiedRouter
|
||||
RolesManagerRolesChecker.key
|
||||
)
|
||||
|
||||
@@ -12,8 +12,7 @@ class RolesStorageWriteServerRoutesConfigurator<T : Role>(
|
||||
private val storage: WriteRolesStorage<T>,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val includeAuthKey: String,
|
||||
private val excludeAuthKey: String = includeAuthKey,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
private val excludeAuthKey: String = includeAuthKey
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
override fun Route.invoke() {
|
||||
route(usersRolesRootPathPart) {
|
||||
|
||||
@@ -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.server.principal
|
||||
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.RolesStorage
|
||||
import io.ktor.http.HttpStatusCode
|
||||
|
||||
@@ -11,8 +11,7 @@ import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class RolesStorageReadServerRoutesConfigurator<T : Role>(
|
||||
private val storage: ReadRolesStorage<T>,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
private val serializer: KSerializer<T>
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
private val userRolesSerializer = ListSerializer(serializer)
|
||||
override fun Route.invoke() {
|
||||
|
||||
@@ -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.statusRootPart
|
||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
||||
import dev.inmo.micro_utils.ktor.common.buildStandardUrl
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpStatusCode
|
||||
|
||||
class StatusFeatureClient(
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.status.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.status.common"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.template.client"/>
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.template.common"/>
|
||||
@@ -5,5 +5,5 @@ import dev.inmo.postssystem.features.auth.client.AuthorizedQualifiers
|
||||
import dev.inmo.postssystem.features.users.common.ReadUsersStorage
|
||||
|
||||
val loader = AuthorizedModuleLoader {
|
||||
single<ReadUsersStorage> { UsersStorageKtorClient(get(AuthorizedQualifiers.ServerUrlQualifier), get()) }
|
||||
single<ReadUsersStorage> { UsersStorageKtorClient(get(AuthorizedQualifiers.ServerUrlQualifier), get(), get()) }
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package dev.inmo.postssystem.features.users.client
|
||||
|
||||
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.repos.ReadCRUDRepo
|
||||
import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadStandardCrudRepo
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
import dev.inmo.micro_utils.repos.ktor.client.crud.KtorReadCRUDRepoClient
|
||||
import io.ktor.client.*
|
||||
import io.ktor.http.*
|
||||
|
||||
class UsersStorageKtorClient(
|
||||
baseUrl: String,
|
||||
unifiedRequester: UnifiedRequester
|
||||
) : ReadUsersStorage, ReadCRUDRepo<User, UserId> by KtorReadStandardCrudRepo(
|
||||
client: HttpClient,
|
||||
contentType: ContentType
|
||||
) : ReadUsersStorage, ReadCRUDRepo<User, UserId> by KtorReadCRUDRepoClient(
|
||||
buildStandardUrl(baseUrl, usersServerPathPart),
|
||||
unifiedRequester,
|
||||
User.serializer(),
|
||||
User.serializer().nullable,
|
||||
UserId.serializer()
|
||||
client,
|
||||
contentType,
|
||||
{ it.long.toString() }
|
||||
)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.users.client"/>
|
||||
@@ -21,7 +21,3 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
disableIncludingJvmCodeInAndroidPart()
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ sealed class User : NewUser {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class DefaultUser(
|
||||
data class RegisteredUser(
|
||||
override val id: UserId,
|
||||
override val firstName: String,
|
||||
override val lastName: String,
|
||||
|
||||
@@ -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.initTable
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
|
||||
class ExposedUsersStorage(override val database: Database) : UsersStorage, AbstractExposedCRUDRepo<User, UserId, NewUser>(
|
||||
tableName = "Users"
|
||||
@@ -15,11 +14,12 @@ class ExposedUsersStorage(override val database: Database) : UsersStorage, Abstr
|
||||
private val lastNameColumn = text("lastName")
|
||||
|
||||
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
|
||||
get() = DefaultUser(
|
||||
get() = RegisteredUser(
|
||||
get(userIdColumn).userId,
|
||||
get(firstNameColumn),
|
||||
get(lastNameColumn),
|
||||
@@ -30,19 +30,19 @@ class ExposedUsersStorage(override val database: Database) : UsersStorage, Abstr
|
||||
initTable()
|
||||
}
|
||||
|
||||
override fun insert(value: NewUser, it: InsertStatement<Number>) {
|
||||
override fun insert(value: NewUser, it: UpdateBuilder<Int>) {
|
||||
it[usernameColumn] = value.username.string
|
||||
it[firstNameColumn] = value.firstName
|
||||
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[firstNameColumn] = value.firstName
|
||||
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(firstNameColumn),
|
||||
get(lastNameColumn),
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.postssystem.features.users.common"/>
|
||||
@@ -1,28 +1,21 @@
|
||||
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.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.routing.Route
|
||||
import io.ktor.server.routing.route
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
|
||||
class UsersStorageServerRoutesConfigurator(
|
||||
private val usersStorage: ReadUsersStorage,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
private val usersStorage: ReadUsersStorage
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
override fun Route.invoke() {
|
||||
authenticate {
|
||||
route(usersServerPathPart) {
|
||||
configureReadStandardCrudRepoRoutes(
|
||||
usersStorage,
|
||||
User.serializer(),
|
||||
User.serializer().nullable,
|
||||
UserId.serializer(),
|
||||
unifiedRouter
|
||||
)
|
||||
configureReadCRUDRepoRoutes(
|
||||
usersStorage
|
||||
) { UserId(it.toLong()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,42 @@
|
||||
[versions]
|
||||
|
||||
kotlin = "1.6.21"
|
||||
kotlin-serialization = "1.3.3"
|
||||
jsuikit = "0.1.1"
|
||||
compose = "1.2.0-alpha01-dev686"
|
||||
microutils = "0.10.4"
|
||||
tgbotapi = "1.1.1"
|
||||
ktor = "2.0.1"
|
||||
klock = "2.7.0"
|
||||
koin = "3.2.0"
|
||||
exposed = "0.38.2"
|
||||
psql = "42.3.0"
|
||||
scrimage = "4.0.31"
|
||||
dokka = "1.6.21"
|
||||
kotlin = "2.0.10"
|
||||
kotlin-serialization = "1.7.1"
|
||||
kotlin-coroutines = "1.8.1"
|
||||
jsuikit = "0.7.6"
|
||||
compose = "1.7.0-alpha02"
|
||||
microutils = "0.22.0"
|
||||
tgbotapi = "17.0.0"
|
||||
ktor = "2.3.11"
|
||||
korlibs = "5.4.0"
|
||||
koin = "3.5.6"
|
||||
exposed = "0.53.0"
|
||||
psql = "42.3.6"
|
||||
scrimage = "4.1.1"
|
||||
dokka = "1.9.20"
|
||||
logback = "1.2.10"
|
||||
uuid = "0.4.0"
|
||||
uuid = "0.8.4"
|
||||
|
||||
android-junit = "4.12"
|
||||
android-test-junit = "1.1.2"
|
||||
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"
|
||||
|
||||
android-coreKtx = "1.7.0"
|
||||
android-coreKtx = "1.12.0"
|
||||
android-recyclerView = "1.2.1"
|
||||
android-appCompat = "1.4.1"
|
||||
android-fragment = "1.6.2"
|
||||
android-compose-material3 = "1.1.2"
|
||||
android-espresso = "3.3.0"
|
||||
android-test = "1.1.2"
|
||||
|
||||
android-props-minSdk = "19"
|
||||
android-props-compileSdk = "32"
|
||||
android-props-buildTools = "32.0.0"
|
||||
android-props-minSdk = "21"
|
||||
android-props-compileSdk = "35"
|
||||
android-props-buildTools = "35.0.0"
|
||||
|
||||
[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-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" }
|
||||
|
||||
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" }
|
||||
|
||||
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" }
|
||||
|
||||
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "android-test-junit" }
|
||||
androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "android-espresso-core" }
|
||||
android-coreKtx = { module = "androidx.core:core-ktx", version.ref = "android-coreKtx" }
|
||||
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
|
||||
|
||||
@@ -100,3 +113,4 @@ buildscript-android-dexcount = { module = "com.getkeepsafe.dexcount:dexcount-gra
|
||||
[plugins]
|
||||
|
||||
compose = { id = "org.jetbrains.compose", version.ref = "compose" }
|
||||
kt-jb-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,4 +1,4 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
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
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
project.version = "$version"
|
||||
project.group = "$group"
|
||||
|
||||
// apply from: "$publishGradlePath"
|
||||
apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
android {
|
||||
androidTarget {
|
||||
publishAllLibraryVariants()
|
||||
compilations.all {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -18,18 +23,15 @@ kotlin {
|
||||
dependencies {
|
||||
implementation kotlin('test-common')
|
||||
implementation kotlin('test-annotations-common')
|
||||
}
|
||||
}
|
||||
androidTest {
|
||||
dependencies {
|
||||
implementation kotlin('test-junit')
|
||||
implementation libs.androidx.test.junit
|
||||
implementation libs.androidx.espresso
|
||||
implementation libs.kt.coroutines.test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allTargetsConfiguration()
|
||||
}
|
||||
|
||||
apply from: "$defaultAndroidSettingsPresetPath"
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
@@ -4,7 +4,13 @@ project.group = "$group"
|
||||
apply from: "$publishGradlePath"
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
jvm {
|
||||
compilations.main {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
@@ -16,6 +22,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation kotlin('test-common')
|
||||
implementation kotlin('test-annotations-common')
|
||||
implementation libs.kotlin.coroutines.test
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +32,9 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allTargetsConfiguration()
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
@@ -13,21 +13,25 @@ kotlin {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation kotlin('stdlib')
|
||||
api libs.kotlin.serialization
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation kotlin('test-common')
|
||||
implementation kotlin('test-annotations-common')
|
||||
implementation libs.kotlin.coroutines.test
|
||||
}
|
||||
}
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation kotlin('test-js')
|
||||
implementation kotlin('test-junit')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allTargetsConfiguration()
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user