feature: init kotlin compose multiplatforme
This commit is contained in:
196 files changed
+1297
-688
No files matched your search
@@ -70,13 +70,17 @@ jobs:
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Run lint
|
||||
run: ./gradlew ktlintCheck
|
||||
# Path scoped to :backend on purpose: :composeApp applies the Android Gradle plugin,
|
||||
# which needs an Android SDK to even configure. Keeping every gradlew invocation on a
|
||||
# fully-qualified project path (with org.gradle.configureondemand=true) lets CI skip
|
||||
# configuring :composeApp entirely, so no Android SDK setup is needed on this runner.
|
||||
run: ./gradlew :backend:ktlintCheck
|
||||
|
||||
- name: Publish ktlint report
|
||||
uses: yutailang0119/action-ktlint@v5
|
||||
if: always()
|
||||
with:
|
||||
report-path: build/reports/ktlint/**/*.xml
|
||||
report-path: backend/build/reports/ktlint/**/*.xml
|
||||
continue-on-error: false
|
||||
|
||||
test:
|
||||
@@ -128,12 +132,12 @@ jobs:
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: test-results
|
||||
path: build/reports/tests/test
|
||||
path: backend/build/reports/tests/test
|
||||
|
||||
- name: Publish Test Report
|
||||
uses: dorny/test-reporter@v3
|
||||
if: always()
|
||||
with:
|
||||
name: JUnit Tests
|
||||
path: build/test-results/test/TEST-*.xml
|
||||
path: backend/build/test-results/test/TEST-*.xml
|
||||
reporter: java-junit
|
||||
@@ -1,9 +1,15 @@
|
||||
.gradle
|
||||
.kotlin/
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### Android / KMP ###
|
||||
local.properties
|
||||
captures/
|
||||
.cxx/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import org.jlleitschuh.gradle.ktlint.KtlintExtension
|
||||
|
||||
val ktorVersion: Provider<String> = providers.gradleProperty("ktor_version")
|
||||
val kotlinVersion: Provider<String> = providers.gradleProperty("kotlin_version")
|
||||
val kotlinSerializationVersion: Provider<String> = providers.gradleProperty("kotlin_serialization_version")
|
||||
val logbackVersion: Provider<String> = providers.gradleProperty("logback_version")
|
||||
val koinVersion: Provider<String> = providers.gradleProperty("koin_version")
|
||||
val kotlinLoggingVersion: Provider<String> = providers.gradleProperty("kotlin_logging_version")
|
||||
val kotestVersion: Provider<String> = providers.gradleProperty("kotest_version")
|
||||
|
||||
plugins {
|
||||
application
|
||||
kotlin("jvm")
|
||||
id("io.ktor.plugin") version "3.5.1"
|
||||
id("org.jetbrains.kotlin.plugin.serialization")
|
||||
id("org.jlleitschuh.gradle.ktlint") version "14.2.0"
|
||||
}
|
||||
|
||||
group = "io.github.flecomte"
|
||||
|
||||
application {
|
||||
mainClass.set("eventDemo.ApplicationKt")
|
||||
|
||||
val isDevelopment: Boolean = project.ext.has("development")
|
||||
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
|
||||
}
|
||||
|
||||
configure<KtlintExtension> {
|
||||
version.set("1.8.0")
|
||||
}
|
||||
ktlint {
|
||||
reporters {
|
||||
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.add("-opt-in=kotlin.uuid.ExperimentalUuidApi")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
jvmArgs("-Djdk.attach.allowAttachSelf=true", "-XX:+EnableDynamicAgentLoading")
|
||||
// Dynamic self-attach (used by MockK/ByteBuddy) times out in Docker containers because the
|
||||
// SIGQUIT-triggered AttachListener handshake never completes there. Loading the byte-buddy
|
||||
// agent jar statically via -javaagent avoids the attach handshake entirely: MockK detects the
|
||||
// pre-installed Instrumentation instance and skips dynamic attach.
|
||||
doFirst {
|
||||
val agentJar =
|
||||
classpath.files.firstOrNull { it.name.startsWith("byte-buddy-agent") }
|
||||
?: error("byte-buddy-agent jar not found on test classpath")
|
||||
jvmArgs("-javaagent:$agentJar")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":shared"))
|
||||
implementation("io.ktor:ktor-server-core-jvm")
|
||||
implementation("io.ktor:ktor-server-auth-jvm")
|
||||
implementation("io.ktor:ktor-server-auth-jwt-jvm")
|
||||
implementation("io.ktor:ktor-server-auto-head-response-jvm")
|
||||
implementation("io.ktor:ktor-server-resources")
|
||||
implementation("io.ktor:ktor-server-content-negotiation-jvm")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm")
|
||||
implementation("io.ktor:ktor-server-websockets-jvm")
|
||||
implementation("io.ktor:ktor-server-cors-jvm")
|
||||
implementation("io.ktor:ktor-server-host-common-jvm")
|
||||
implementation("io.ktor:ktor-server-status-pages-jvm")
|
||||
implementation("io.ktor:ktor-server-netty-jvm")
|
||||
implementation("io.ktor:ktor-server-data-conversion")
|
||||
implementation("io.ktor:ktor-client-content-negotiation")
|
||||
implementation("io.ktor:ktor-client-auth")
|
||||
implementation("ch.qos.logback:logback-classic:${logbackVersion.get()}")
|
||||
implementation("io.insert-koin:koin-ktor:${koinVersion.get()}")
|
||||
implementation("io.insert-koin:koin-logger-slf4j:${koinVersion.get()}")
|
||||
implementation("io.github.oshai:kotlin-logging-jvm:${kotlinLoggingVersion.get()}")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:${kotlinSerializationVersion.get()}")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.2")
|
||||
implementation("org.postgresql:postgresql:42.7.13")
|
||||
implementation("com.zaxxer:HikariCP:6.3.0")
|
||||
implementation("com.rabbitmq:amqp-client:5.25.0")
|
||||
implementation("com.password4j:password4j:1.8.4")
|
||||
|
||||
// Force version of sub library (for security)
|
||||
implementation("commons-codec:commons-codec:1.13")
|
||||
|
||||
testImplementation("io.kotest:kotest-extensions-koin:${kotestVersion.get()}")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:${kotlinVersion.get()}")
|
||||
testImplementation("io.ktor:ktor-server-test-host-jvm:${ktorVersion.get()}")
|
||||
testImplementation("io.kotest:kotest-runner-junit5:${kotestVersion.get()}")
|
||||
testImplementation("io.mockk:mockk:1.14.11")
|
||||
testImplementation("com.tngtech.archunit:archunit-junit5:1.3.0")
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -2,7 +2,7 @@ package eventDemo.contexts.auth.application.eventStores
|
||||
|
||||
import eventDemo.contexts.auth.application.ports.UserEventStore
|
||||
import eventDemo.contexts.auth.domain.User
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
class UserEventStoreRepository(
|
||||
val eventStore: UserEventStore,
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.contexts.auth.application.eventStores
|
||||
|
||||
import eventDemo.contexts.auth.domain.User
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
interface UserRepository {
|
||||
fun get(id: UserId): User?
|
||||
+1
-1
@@ -2,6 +2,6 @@ package eventDemo.contexts.auth.application.ports
|
||||
|
||||
import eventDemo.contexts.auth.domain.events.UserEvent
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
interface UserEventStore : EventStore<UserEvent, UserId>
|
||||
File renamed without changes.
+1
-1
@@ -2,7 +2,7 @@ package eventDemo.contexts.auth.domain
|
||||
|
||||
import eventDemo.contexts.auth.domain.events.NewUserCreatedEvent
|
||||
import eventDemo.contexts.auth.domain.events.UserEvent
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package eventDemo.contexts.auth.domain.events
|
||||
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.contexts.auth.domain.events
|
||||
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -5,7 +5,7 @@ import com.auth0.jwt.algorithms.Algorithm
|
||||
import eventDemo.configuration.configuration
|
||||
import eventDemo.contexts.auth.domain.User
|
||||
import eventDemo.contexts.auth.infrastructure.persistence.projection.UserProjection
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.auth.authentication
|
||||
+1
-1
@@ -4,7 +4,7 @@ import eventDemo.contexts.auth.application.ports.UserEventStore
|
||||
import eventDemo.contexts.auth.domain.events.UserEvent
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
/**
|
||||
* A stream to publish and read the user events.
|
||||
+1
-1
@@ -4,7 +4,7 @@ import eventDemo.contexts.auth.application.ports.UserEventStore
|
||||
import eventDemo.contexts.auth.domain.events.UserEvent
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.sql.DataSource
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package eventDemo.contexts.auth.infrastructure.persistence.projection
|
||||
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
data class UserProjection(
|
||||
val id: UserId,
|
||||
+5
-4
@@ -3,9 +3,10 @@ package eventDemo.contexts.auth.infrastructure.persistence.projection
|
||||
import eventDemo.contexts.auth.application.ports.UserProjectionRepository
|
||||
import eventDemo.contexts.auth.infrastructure.checkPassword
|
||||
import eventDemo.contexts.auth.infrastructure.hashPassword
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import java.util.UUID
|
||||
import eventDemo.shared.ids.UserId
|
||||
import javax.sql.DataSource
|
||||
import kotlin.uuid.Uuid
|
||||
import kotlin.uuid.toJavaUuid
|
||||
|
||||
class UserProjectionRepositoryInPostgresql(
|
||||
val dataSource: DataSource,
|
||||
@@ -24,7 +25,7 @@ class UserProjectionRepositoryInPostgresql(
|
||||
}.use { resultSet ->
|
||||
if (resultSet.next()) {
|
||||
UserProjection(
|
||||
id = UserId(UUID.fromString(resultSet.getString("id"))),
|
||||
id = UserId(Uuid.parse(resultSet.getString("id"))),
|
||||
username = resultSet.getString("username"),
|
||||
password = resultSet.getString("password"),
|
||||
)
|
||||
@@ -42,7 +43,7 @@ class UserProjectionRepositoryInPostgresql(
|
||||
values (?, ?)
|
||||
""".trimIndent(),
|
||||
).use {
|
||||
it.setObject(1, user.id)
|
||||
it.setObject(1, user.id.id.toJavaUuid())
|
||||
it.setString(2, user.username)
|
||||
it.executeUpdate()
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+4
-4
@@ -1,11 +1,11 @@
|
||||
package eventDemo.contexts.game.application.channels
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.GameCommand
|
||||
import eventDemo.contexts.game.application.notification.CommandSubscriber
|
||||
import eventDemo.contexts.game.application.notification.EventToNotificationSubscriber
|
||||
import eventDemo.contexts.game.application.notification.models.Notification
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.game.command.GameCommand
|
||||
import eventDemo.shared.game.notification.Notification
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
File renamed without changes.
+6
-6
@@ -1,11 +1,11 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.GameCommand
|
||||
import eventDemo.contexts.game.application.command.models.JoinTheGameCommand
|
||||
import eventDemo.contexts.game.application.command.models.PlayCardCommand
|
||||
import eventDemo.contexts.game.application.command.models.ReadyToPlayCommand
|
||||
import eventDemo.contexts.game.application.command.models.TakeCartFromDrawPileCommand
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.shared.game.command.GameCommand
|
||||
import eventDemo.shared.game.command.JoinTheGameCommand
|
||||
import eventDemo.shared.game.command.PlayCardCommand
|
||||
import eventDemo.shared.game.command.ReadyToPlayCommand
|
||||
import eventDemo.shared.game.command.TakeCartFromDrawPileCommand
|
||||
import eventDemo.shared.ids.GameId
|
||||
import java.util.Collections
|
||||
|
||||
class GameCommandHandlerDispatcher(
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.GameCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||
import eventDemo.libs.command.Command
|
||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||
import eventDemo.shared.command.Command
|
||||
import eventDemo.shared.game.command.GameCommand
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
+1
-1
@@ -1,10 +1,10 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.auth.application.eventStores.UserRepository
|
||||
import eventDemo.contexts.game.application.command.models.JoinTheGameCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
||||
import eventDemo.shared.game.command.JoinTheGameCommand
|
||||
|
||||
/**
|
||||
* A command to perform an action to play a new card
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.PlayCardCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
||||
import eventDemo.shared.game.command.PlayCardCommand
|
||||
|
||||
/**
|
||||
* A command to perform an action to play a new card
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.ReadyToPlayCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
||||
import eventDemo.shared.game.command.ReadyToPlayCommand
|
||||
|
||||
/**
|
||||
* A command to set as ready to play
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.application.command.handlers
|
||||
|
||||
import eventDemo.contexts.game.application.command.models.TakeCartFromDrawPileCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
||||
import eventDemo.shared.game.command.TakeCartFromDrawPileCommand
|
||||
|
||||
/**
|
||||
* A command to draw card on draw pile.
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.application.eventStores
|
||||
|
||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
class GameEventStoreRepository(
|
||||
val eventStore: GameEventStore,
|
||||
+1
-1
@@ -1,10 +1,10 @@
|
||||
package eventDemo.contexts.game.application.eventStores
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameInit
|
||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
interface GameRepository {
|
||||
fun get(id: GameId): Game?
|
||||
File renamed without changes.
File renamed without changes.
+12
-12
@@ -1,16 +1,5 @@
|
||||
package eventDemo.contexts.game.application.notification
|
||||
|
||||
import eventDemo.contexts.game.application.notification.models.ItsTheTurnOfNotification
|
||||
import eventDemo.contexts.game.application.notification.models.Notification
|
||||
import eventDemo.contexts.game.application.notification.models.PilesShuffledNotification
|
||||
import eventDemo.contexts.game.application.notification.models.PlayerAsJoinTheGameNotification
|
||||
import eventDemo.contexts.game.application.notification.models.PlayerAsPlayACardNotification
|
||||
import eventDemo.contexts.game.application.notification.models.PlayerHavePassNotification
|
||||
import eventDemo.contexts.game.application.notification.models.PlayerWasReadyNotification
|
||||
import eventDemo.contexts.game.application.notification.models.PlayerWinNotification
|
||||
import eventDemo.contexts.game.application.notification.models.TheGameWasStartedNotification
|
||||
import eventDemo.contexts.game.application.notification.models.WelcomeToTheGameNotification
|
||||
import eventDemo.contexts.game.application.notification.models.YourNewCardNotification
|
||||
import eventDemo.contexts.game.domain.events.CardIsPlayedEvent
|
||||
import eventDemo.contexts.game.domain.events.DrawFilledWithDiscardEvent
|
||||
import eventDemo.contexts.game.domain.events.GameCreatedEvent
|
||||
@@ -23,7 +12,18 @@ import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.game.notification.ItsTheTurnOfNotification
|
||||
import eventDemo.shared.game.notification.Notification
|
||||
import eventDemo.shared.game.notification.PilesShuffledNotification
|
||||
import eventDemo.shared.game.notification.PlayerAsJoinTheGameNotification
|
||||
import eventDemo.shared.game.notification.PlayerAsPlayACardNotification
|
||||
import eventDemo.shared.game.notification.PlayerHavePassNotification
|
||||
import eventDemo.shared.game.notification.PlayerWasReadyNotification
|
||||
import eventDemo.shared.game.notification.PlayerWinNotification
|
||||
import eventDemo.shared.game.notification.TheGameWasStartedNotification
|
||||
import eventDemo.shared.game.notification.WelcomeToTheGameNotification
|
||||
import eventDemo.shared.game.notification.YourNewCardNotification
|
||||
import eventDemo.shared.ids.UserId
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||
|
||||
+4
-4
@@ -1,7 +1,6 @@
|
||||
package eventDemo.contexts.game.application.notification
|
||||
|
||||
import eventDemo.contexts.game.application.command.handlers.GameCommandHandlerDispatcher
|
||||
import eventDemo.contexts.game.application.command.models.GameCommand
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Command
|
||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.CurrentUserId
|
||||
@@ -9,12 +8,13 @@ import eventDemo.contexts.game.application.logging.LoggingContextKeys.Event
|
||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Game
|
||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Notification
|
||||
import eventDemo.contexts.game.application.logging.withLoggingContext
|
||||
import eventDemo.contexts.game.application.notification.models.Notification
|
||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.libs.bus.Bus
|
||||
import eventDemo.libs.command.CommandUnicityChecker
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.game.command.GameCommand
|
||||
import eventDemo.shared.game.notification.Notification
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.ids.UserId
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.Job
|
||||
File renamed without changes.
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.contexts.game.application.ports
|
||||
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
interface GameEventStore : EventStore<GameEvent, GameId>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package eventDemo.domain.event.projection
|
||||
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameList
|
||||
import eventDemo.shared.game.projection.GameList
|
||||
|
||||
interface GameListRepository {
|
||||
fun getList(
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package eventDemo.contexts.game.application.ports
|
||||
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameProjection
|
||||
import eventDemo.libs.bus.Bus
|
||||
import eventDemo.shared.game.projection.GameProjection
|
||||
|
||||
interface GameProjectionBus : Bus<GameProjection>
|
||||
+1
-1
@@ -9,7 +9,7 @@ import eventDemo.contexts.game.domain.events.NewPlayerEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerHaveDrawCardEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameList
|
||||
import eventDemo.shared.game.projection.GameList
|
||||
|
||||
fun GameList.applyEvent(event: GameEvent): GameList =
|
||||
when (event) {
|
||||
File renamed without changes.
+8
-8
@@ -1,15 +1,15 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.Card
|
||||
import eventDemo.contexts.game.domain.game.Card.Color
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.Card
|
||||
import eventDemo.shared.game.Card.Color
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* An [GameEvent] to represent a played card.
|
||||
@@ -24,7 +24,7 @@ data class CardIsPlayedEvent(
|
||||
) : GameEvent,
|
||||
PlayerActionEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
|
||||
val theColorCard get() = if (card is Card.CardWithColor) card.color else chosenColor
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
||||
import eventDemo.contexts.game.domain.game.DrawPile
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.DiscardPile
|
||||
import eventDemo.shared.game.DrawPile
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* When the Pile are shuffled after the draw pille was empty
|
||||
@@ -21,6 +21,6 @@ class DrawFilledWithDiscardEvent(
|
||||
override val version: Int,
|
||||
) : GameEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when all players are ready.
|
||||
@@ -17,6 +17,6 @@ data class GameCreatedEvent(
|
||||
override val version: Int,
|
||||
) : GameEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.GameIdSerializer
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.GameIdSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
+10
-10
@@ -1,17 +1,17 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
||||
import eventDemo.contexts.game.domain.game.DrawPile
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.domain.game.PlayerHand
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.DiscardPile
|
||||
import eventDemo.shared.game.DrawPile
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.game.PlayerHand
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when all players are ready.
|
||||
@@ -27,6 +27,6 @@ data class GameStartedEvent(
|
||||
override val version: Int,
|
||||
) : GameEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+6
-6
@@ -1,13 +1,13 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* An [GameEvent] to represent a new player joining the game.
|
||||
@@ -22,6 +22,6 @@ data class NewPlayerEvent(
|
||||
override val playerId: Player.PlayerId get() = player.id
|
||||
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.shared.game.Player
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
+8
-8
@@ -1,15 +1,15 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.Card
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.Card
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when a player can play.
|
||||
@@ -24,6 +24,6 @@ data class PlayerHaveDrawCardEvent(
|
||||
) : GameEvent,
|
||||
PlayerActionEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when a player is ready.
|
||||
@@ -22,6 +22,6 @@ data class PlayerReadyEvent(
|
||||
) : GameEvent,
|
||||
PlayerActionEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
package eventDemo.contexts.game.domain.events
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when a player is ready.
|
||||
@@ -22,6 +22,6 @@ data class PlayerWinEvent(
|
||||
) : GameEvent,
|
||||
PlayerActionEvent {
|
||||
@Serializable(with = EventIdSerializer::class)
|
||||
override val eventId: EventId = EventId(UUID.randomUUID())
|
||||
override val eventId: EventId = EventId(Uuid.random())
|
||||
override val createdAt: Instant = Clock.System.now()
|
||||
}
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
package eventDemo.contexts.game.domain.game.errors
|
||||
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.Card
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.contexts.game.domain.game.gameState.Deck
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||
import eventDemo.shared.game.Card
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.game.PlayerList
|
||||
|
||||
abstract class GameException(
|
||||
message: String,
|
||||
+2
-2
@@ -9,10 +9,10 @@ import eventDemo.contexts.game.domain.events.NewPlayerEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerHaveDrawCardEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.contexts.game.domain.game.errors.GameException
|
||||
import eventDemo.contexts.game.domain.game.errors.InconsistentEventVersionException
|
||||
import eventDemo.shared.game.PlayerList
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
sealed interface Game {
|
||||
val aggregateId: GameId
|
||||
+8
-8
@@ -4,18 +4,18 @@ import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.events.GameStartedEvent
|
||||
import eventDemo.contexts.game.domain.events.NewPlayerEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||
import eventDemo.contexts.game.domain.game.Card
|
||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
||||
import eventDemo.contexts.game.domain.game.DrawPile
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.domain.game.PlayerHand
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.contexts.game.domain.game.errors.AllPlayerNotReadyException
|
||||
import eventDemo.contexts.game.domain.game.errors.DeckMissingCardsException
|
||||
import eventDemo.contexts.game.domain.game.errors.NeedMorePlayersToStartGameException
|
||||
import eventDemo.contexts.game.domain.game.errors.ThePlayerIsNotInTheGameException
|
||||
import eventDemo.sharedKernel.UserId
|
||||
import eventDemo.shared.game.Card
|
||||
import eventDemo.shared.game.DiscardPile
|
||||
import eventDemo.shared.game.DrawPile
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.game.PlayerHand
|
||||
import eventDemo.shared.game.PlayerList
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.ids.UserId
|
||||
|
||||
data class GameCreated(
|
||||
override val aggregateId: GameId,
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.domain.game.gameState
|
||||
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.game.PlayerList
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
data class GameEnded(
|
||||
override val aggregateId: GameId,
|
||||
+2
-2
@@ -2,8 +2,8 @@ package eventDemo.contexts.game.domain.game.gameState
|
||||
|
||||
import eventDemo.contexts.game.domain.events.GameCreatedEvent
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.shared.game.PlayerList
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
data class GameInit(
|
||||
override val aggregateId: GameId,
|
||||
+7
-7
@@ -6,13 +6,6 @@ import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerActionEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerHaveDrawCardEvent
|
||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
||||
import eventDemo.contexts.game.domain.game.Card
|
||||
import eventDemo.contexts.game.domain.game.Card.Color
|
||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
||||
import eventDemo.contexts.game.domain.game.DrawPile
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.domain.game.PlayerList
|
||||
import eventDemo.contexts.game.domain.game.errors.InconsistentGameException
|
||||
import eventDemo.contexts.game.domain.game.errors.ItsNotTheTurnException
|
||||
import eventDemo.contexts.game.domain.game.errors.TheCardHasNoColorException
|
||||
@@ -22,6 +15,13 @@ import eventDemo.contexts.game.domain.game.errors.ThePlayerHasRemainingCardsExce
|
||||
import eventDemo.contexts.game.domain.game.errors.ThePlayerIsNotInTheGameException
|
||||
import eventDemo.contexts.game.domain.game.errors.ThePlayerMustPlayACardException
|
||||
import eventDemo.contexts.game.domain.game.gameState.Game.Direction
|
||||
import eventDemo.shared.game.Card
|
||||
import eventDemo.shared.game.Card.Color
|
||||
import eventDemo.shared.game.DiscardPile
|
||||
import eventDemo.shared.game.DrawPile
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.game.PlayerList
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
fun PlayerList.nextPlayerTurn(
|
||||
lastPlayerId: Player.PlayerId,
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-15
@@ -1,5 +1,6 @@
|
||||
package eventDemo.contexts.game.infrastructure.configuration.ktor
|
||||
|
||||
import eventDemo.shared.http.HttpErrorBadRequest
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -10,7 +11,6 @@ import io.ktor.server.plugins.cors.routing.CORS
|
||||
import io.ktor.server.plugins.statuspages.StatusPages
|
||||
import io.ktor.server.resources.Resources
|
||||
import io.ktor.server.response.respondText
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
fun Application.configureHttpRouting() {
|
||||
install(CORS) {
|
||||
@@ -38,17 +38,3 @@ fun Application.configureHttpRouting() {
|
||||
class BadRequestException(
|
||||
val httpError: HttpErrorBadRequest,
|
||||
) : Exception()
|
||||
|
||||
@Serializable
|
||||
class HttpErrorBadRequest(
|
||||
val title: String = HttpStatusCode.BadRequest.description,
|
||||
val invalidParams: List<InvalidParam> = emptyList(),
|
||||
) {
|
||||
val statusCode: Int = HttpStatusCode.BadRequest.value
|
||||
|
||||
@Serializable
|
||||
data class InvalidParam(
|
||||
val name: String,
|
||||
val reason: String,
|
||||
)
|
||||
}
|
||||
+11
-11
@@ -1,21 +1,21 @@
|
||||
package eventDemo.contexts.game.infrastructure.configuration.ktor
|
||||
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.domain.game.Player
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.CommandIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.GameIdSerializer
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
||||
import eventDemo.libs.command.CommandId
|
||||
import eventDemo.libs.eventSource.EventId
|
||||
import eventDemo.libs.serializer.UUIDSerializer
|
||||
import eventDemo.shared.game.Player
|
||||
import eventDemo.shared.ids.CommandId
|
||||
import eventDemo.shared.ids.EventId
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.CommandIdSerializer
|
||||
import eventDemo.shared.serializers.EventIdSerializer
|
||||
import eventDemo.shared.serializers.GameIdSerializer
|
||||
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||
import eventDemo.shared.serializers.UUIDSerializer
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) {
|
||||
@@ -29,7 +29,7 @@ fun defaultJsonSerializer(): Json =
|
||||
Json {
|
||||
serializersModule =
|
||||
SerializersModule {
|
||||
contextual(UUID::class) { UUIDSerializer }
|
||||
contextual(Uuid::class) { UUIDSerializer }
|
||||
contextual(GameId::class) { GameIdSerializer }
|
||||
contextual(EventId::class) { EventIdSerializer }
|
||||
contextual(CommandId::class) { CommandIdSerializer }
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -2,9 +2,9 @@ package eventDemo.contexts.game.infrastructure.persistence.eventStore
|
||||
|
||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
||||
import eventDemo.shared.ids.GameId
|
||||
|
||||
/**
|
||||
* A stream to publish and read the played card event.
|
||||
+1
-1
@@ -2,9 +2,9 @@ package eventDemo.contexts.game.infrastructure.persistence.eventStore
|
||||
|
||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||
import eventDemo.contexts.game.domain.events.GameEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
||||
import eventDemo.shared.ids.GameId
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.sql.DataSource
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ import eventDemo.contexts.game.application.ports.GameEventBus
|
||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
||||
import eventDemo.contexts.game.application.projections.applyEvent
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameList
|
||||
import eventDemo.domain.event.projection.GameListRepository
|
||||
import eventDemo.shared.game.projection.GameList
|
||||
import eventDemo.shared.ids.GameId
|
||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
package eventDemo.contexts.game.infrastructure.persistence.projections.bus
|
||||
|
||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameProjection
|
||||
import eventDemo.libs.bus.Bus
|
||||
import eventDemo.libs.bus.BusInMemory
|
||||
import eventDemo.shared.game.projection.GameProjection
|
||||
import java.util.UUID
|
||||
|
||||
class GameProjectionBusInMemory :
|
||||
+1
-1
@@ -2,9 +2,9 @@ package eventDemo.contexts.game.infrastructure.persistence.projections.bus
|
||||
|
||||
import com.rabbitmq.client.ConnectionFactory
|
||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameProjection
|
||||
import eventDemo.libs.bus.Bus
|
||||
import eventDemo.libs.bus.BusInRabbitMQ
|
||||
import eventDemo.shared.game.projection.GameProjection
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.util.UUID
|
||||
|
||||
File renamed without changes.
+2
-2
@@ -3,8 +3,8 @@ package eventDemo.contexts.game.infrastructure.rest
|
||||
import eventDemo.contexts.game.application.eventStores.GameRepository
|
||||
import eventDemo.contexts.game.application.notification.toNotification
|
||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.GameIdSerializer
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.shared.serializers.GameIdSerializer
|
||||
import eventDemo.sharedKernel.currentUserId
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.resources.Resource
|
||||
+3
-3
@@ -1,22 +1,22 @@
|
||||
package eventDemo.contexts.game.infrastructure.websocket
|
||||
|
||||
import eventDemo.contexts.game.application.channels.GameChannelsSubscriber
|
||||
import eventDemo.contexts.game.domain.game.GameId
|
||||
import eventDemo.libs.helpers.fromFrameChannel
|
||||
import eventDemo.libs.helpers.toObjectChannel
|
||||
import eventDemo.shared.ids.GameId
|
||||
import eventDemo.sharedKernel.currentUserId
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.websocket.webSocket
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@DelicateCoroutinesApi
|
||||
fun Route.gameWebSocket(channelSubscriber: GameChannelsSubscriber) {
|
||||
authenticate {
|
||||
webSocket("/games/{id}") {
|
||||
channelSubscriber.subscribePlayerToGameChannels(
|
||||
gameId = GameId(UUID.fromString(call.parameters["id"]!!)),
|
||||
gameId = GameId(Uuid.parse(call.parameters["id"]!!)),
|
||||
userId = call.currentUserId,
|
||||
incomingCommandChannel = toObjectChannel(incoming),
|
||||
sendNotificationChannel = fromFrameChannel(outgoing),
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
@@ -1,5 +1,7 @@
|
||||
package eventDemo.libs.command
|
||||
|
||||
import eventDemo.shared.command.Command
|
||||
import eventDemo.shared.ids.CommandId
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
@@ -0,0 +1,16 @@
|
||||
package eventDemo.libs.eventSource
|
||||
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import eventDemo.shared.ids.EventId
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
/**
|
||||
* The basic interface for an Event
|
||||
* @see eventDemo.libs.eventSource.eventStore.EventStream
|
||||
*/
|
||||
interface Event<ID : AggregateId> {
|
||||
val eventId: EventId
|
||||
val aggregateId: ID
|
||||
val createdAt: Instant
|
||||
val version: Int
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||
|
||||
interface EventStore<E : Event<ID>, ID : AggregateId> {
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import javax.sql.DataSource
|
||||
|
||||
class EventStoreInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import java.util.Queue
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
+7
-6
@@ -1,12 +1,13 @@
|
||||
package eventDemo.libs.eventSource.eventStore
|
||||
|
||||
import eventDemo.libs.eventSource.AggregateId
|
||||
import eventDemo.libs.eventSource.Event
|
||||
import eventDemo.shared.ids.AggregateId
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||
import org.postgresql.util.PGobject
|
||||
import org.postgresql.util.PSQLException
|
||||
import javax.sql.DataSource
|
||||
import kotlin.uuid.toJavaUuid
|
||||
|
||||
/**
|
||||
* An In-Memory implementation of an event stream.
|
||||
@@ -39,8 +40,8 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||
on conflict (id) do nothing
|
||||
""".trimIndent(),
|
||||
).use {
|
||||
it.setObject(1, event.eventId.id)
|
||||
it.setObject(2, event.aggregateId.id)
|
||||
it.setObject(1, event.eventId.id.toJavaUuid())
|
||||
it.setObject(2, event.aggregateId.id.toJavaUuid())
|
||||
it.setInt(3, event.version)
|
||||
it.setObject(4, PGJsonb(objectToString(event)))
|
||||
it.executeUpdate()
|
||||
@@ -69,7 +70,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||
order by version asc
|
||||
""".trimIndent(),
|
||||
).use {
|
||||
it.setObject(1, aggregateId.id)
|
||||
it.setObject(1, aggregateId.id.toJavaUuid())
|
||||
it.executeQuery().use { resultSet ->
|
||||
buildSet {
|
||||
while (resultSet.next()) {
|
||||
@@ -95,7 +96,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||
order by version asc
|
||||
""".trimIndent(),
|
||||
).use {
|
||||
it.setObject(1, aggregateId.id)
|
||||
it.setObject(1, aggregateId.id.toJavaUuid())
|
||||
it.executeQuery().use { resultSet ->
|
||||
resultSet.next()
|
||||
}
|
||||
@@ -116,7 +117,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||
).use { stmt ->
|
||||
stmt.setInt(1, version.first)
|
||||
stmt.setInt(2, version.last)
|
||||
stmt.setObject(3, aggregateId.id)
|
||||
stmt.setObject(3, aggregateId.id.toJavaUuid())
|
||||
stmt.executeQuery().use { resultSet ->
|
||||
buildSet {
|
||||
while (resultSet.next()) {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-2
@@ -1,12 +1,13 @@
|
||||
package eventDemo.sharedKernel
|
||||
|
||||
import eventDemo.shared.ids.UserId
|
||||
import io.ktor.server.application.ApplicationCall
|
||||
import io.ktor.server.auth.jwt.JWTPrincipal
|
||||
import io.ktor.server.auth.principal
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
internal val ApplicationCall.currentUserId: UserId
|
||||
get() =
|
||||
principal<JWTPrincipal>()!!.run {
|
||||
UserId(UUID.fromString(payload.getClaim("userid").asString()))
|
||||
UserId(Uuid.parse(payload.getClaim("userid").asString()))
|
||||
}
|
||||
File renamed without changes.
Loaded 100 of 196 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user