feature: init kotlin compose multiplatforme
This commit is contained in:
@@ -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")
|
||||
}
|
||||
+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>
|
||||
+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
|
||||
+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()
|
||||
}
|
||||
+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
|
||||
+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?
|
||||
+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
|
||||
+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) {
|
||||
+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,
|
||||
+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 }
|
||||
+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
|
||||
|
||||
+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),
|
||||
+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()) {
|
||||
+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()))
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user