feature: init kotlin compose multiplatforme #50
No files matched your search
@@ -70,13 +70,17 @@ jobs:
|
|||||||
run: chmod +x gradlew
|
run: chmod +x gradlew
|
||||||
|
|
||||||
- name: Run lint
|
- 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
|
- name: Publish ktlint report
|
||||||
uses: yutailang0119/action-ktlint@v5
|
uses: yutailang0119/action-ktlint@v5
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
report-path: build/reports/ktlint/**/*.xml
|
report-path: backend/build/reports/ktlint/**/*.xml
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@@ -128,12 +132,12 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: test-results
|
name: test-results
|
||||||
path: build/reports/tests/test
|
path: backend/build/reports/tests/test
|
||||||
|
|
||||||
- name: Publish Test Report
|
- name: Publish Test Report
|
||||||
uses: dorny/test-reporter@v3
|
uses: dorny/test-reporter@v3
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: JUnit Tests
|
name: JUnit Tests
|
||||||
path: build/test-results/test/TEST-*.xml
|
path: backend/build/test-results/test/TEST-*.xml
|
||||||
reporter: java-junit
|
reporter: java-junit
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
.gradle
|
.gradle
|
||||||
|
.kotlin/
|
||||||
build/
|
build/
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
!**/src/main/**/build/
|
!**/src/main/**/build/
|
||||||
!**/src/test/**/build/
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### Android / KMP ###
|
||||||
|
local.properties
|
||||||
|
captures/
|
||||||
|
.cxx/
|
||||||
|
|
||||||
### STS ###
|
### STS ###
|
||||||
.apt_generated
|
.apt_generated
|
||||||
.classpath
|
.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.application.ports.UserEventStore
|
||||||
import eventDemo.contexts.auth.domain.User
|
import eventDemo.contexts.auth.domain.User
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
|
|
||||||
class UserEventStoreRepository(
|
class UserEventStoreRepository(
|
||||||
val eventStore: UserEventStore,
|
val eventStore: UserEventStore,
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.contexts.auth.application.eventStores
|
package eventDemo.contexts.auth.application.eventStores
|
||||||
|
|
||||||
import eventDemo.contexts.auth.domain.User
|
import eventDemo.contexts.auth.domain.User
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
|
|
||||||
interface UserRepository {
|
interface UserRepository {
|
||||||
fun get(id: UserId): User?
|
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.contexts.auth.domain.events.UserEvent
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
|
|
||||||
interface UserEventStore : EventStore<UserEvent, 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.NewUserCreatedEvent
|
||||||
import eventDemo.contexts.auth.domain.events.UserEvent
|
import eventDemo.contexts.auth.domain.events.UserEvent
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.contexts.auth.domain.events
|
package eventDemo.contexts.auth.domain.events
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.contexts.auth.domain.events
|
package eventDemo.contexts.auth.domain.events
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@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.configuration.configuration
|
||||||
import eventDemo.contexts.auth.domain.User
|
import eventDemo.contexts.auth.domain.User
|
||||||
import eventDemo.contexts.auth.infrastructure.persistence.projection.UserProjection
|
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.http.HttpStatusCode
|
||||||
import io.ktor.server.application.Application
|
import io.ktor.server.application.Application
|
||||||
import io.ktor.server.auth.authentication
|
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.contexts.auth.domain.events.UserEvent
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream to publish and read the user events.
|
* 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.contexts.auth.domain.events.UserEvent
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStore
|
import eventDemo.libs.eventSource.eventStore.EventStore
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eventDemo.contexts.auth.infrastructure.persistence.projection
|
package eventDemo.contexts.auth.infrastructure.persistence.projection
|
||||||
|
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
|
|
||||||
data class UserProjection(
|
data class UserProjection(
|
||||||
val id: UserId,
|
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.application.ports.UserProjectionRepository
|
||||||
import eventDemo.contexts.auth.infrastructure.checkPassword
|
import eventDemo.contexts.auth.infrastructure.checkPassword
|
||||||
import eventDemo.contexts.auth.infrastructure.hashPassword
|
import eventDemo.contexts.auth.infrastructure.hashPassword
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.UserId
|
||||||
import java.util.UUID
|
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
import kotlin.uuid.toJavaUuid
|
||||||
|
|
||||||
class UserProjectionRepositoryInPostgresql(
|
class UserProjectionRepositoryInPostgresql(
|
||||||
val dataSource: DataSource,
|
val dataSource: DataSource,
|
||||||
@@ -24,7 +25,7 @@ class UserProjectionRepositoryInPostgresql(
|
|||||||
}.use { resultSet ->
|
}.use { resultSet ->
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
UserProjection(
|
UserProjection(
|
||||||
id = UserId(UUID.fromString(resultSet.getString("id"))),
|
id = UserId(Uuid.parse(resultSet.getString("id"))),
|
||||||
username = resultSet.getString("username"),
|
username = resultSet.getString("username"),
|
||||||
password = resultSet.getString("password"),
|
password = resultSet.getString("password"),
|
||||||
)
|
)
|
||||||
@@ -42,7 +43,7 @@ class UserProjectionRepositoryInPostgresql(
|
|||||||
values (?, ?)
|
values (?, ?)
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
).use {
|
).use {
|
||||||
it.setObject(1, user.id)
|
it.setObject(1, user.id.id.toJavaUuid())
|
||||||
it.setString(2, user.username)
|
it.setString(2, user.username)
|
||||||
it.executeUpdate()
|
it.executeUpdate()
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
package eventDemo.contexts.game.application.channels
|
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.CommandSubscriber
|
||||||
import eventDemo.contexts.game.application.notification.EventToNotificationSubscriber
|
import eventDemo.contexts.game.application.notification.EventToNotificationSubscriber
|
||||||
import eventDemo.contexts.game.application.notification.models.Notification
|
import eventDemo.shared.game.command.GameCommand
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.notification.Notification
|
||||||
import eventDemo.sharedKernel.UserId
|
import eventDemo.shared.ids.GameId
|
||||||
|
import eventDemo.shared.ids.UserId
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
import kotlinx.coroutines.channels.SendChannel
|
import kotlinx.coroutines.channels.SendChannel
|
||||||
File renamed without changes.
+6
-6
@@ -1,11 +1,11 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
package eventDemo.contexts.game.application.command.handlers
|
||||||
|
|
||||||
import eventDemo.contexts.game.application.command.models.GameCommand
|
import eventDemo.shared.game.command.GameCommand
|
||||||
import eventDemo.contexts.game.application.command.models.JoinTheGameCommand
|
import eventDemo.shared.game.command.JoinTheGameCommand
|
||||||
import eventDemo.contexts.game.application.command.models.PlayCardCommand
|
import eventDemo.shared.game.command.PlayCardCommand
|
||||||
import eventDemo.contexts.game.application.command.models.ReadyToPlayCommand
|
import eventDemo.shared.game.command.ReadyToPlayCommand
|
||||||
import eventDemo.contexts.game.application.command.models.TakeCartFromDrawPileCommand
|
import eventDemo.shared.game.command.TakeCartFromDrawPileCommand
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.ids.GameId
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
|
||||||
class GameCommandHandlerDispatcher(
|
class GameCommandHandlerDispatcher(
|
||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
import eventDemo.contexts.game.domain.events.GameEvent
|
||||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||||
import eventDemo.libs.command.Command
|
|
||||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||||
|
import eventDemo.shared.command.Command
|
||||||
|
import eventDemo.shared.game.command.GameCommand
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
+1
-1
@@ -1,10 +1,10 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
package eventDemo.contexts.game.application.command.handlers
|
||||||
|
|
||||||
import eventDemo.contexts.auth.application.eventStores.UserRepository
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
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
|
* A command to perform an action to play a new card
|
||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
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
|
* A command to perform an action to play a new card
|
||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
||||||
|
import eventDemo.shared.game.command.ReadyToPlayCommand
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A command to set as ready to play
|
* A command to set as ready to play
|
||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.application.command.handlers
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.ports.GameEventBus
|
import eventDemo.contexts.game.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
||||||
|
import eventDemo.shared.game.command.TakeCartFromDrawPileCommand
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A command to draw card on draw pile.
|
* A command to draw card on draw pile.
|
||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.application.eventStores
|
package eventDemo.contexts.game.application.eventStores
|
||||||
|
|
||||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
|
||||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
class GameEventStoreRepository(
|
class GameEventStoreRepository(
|
||||||
val eventStore: GameEventStore,
|
val eventStore: GameEventStore,
|
||||||
+1
-1
@@ -1,10 +1,10 @@
|
|||||||
package eventDemo.contexts.game.application.eventStores
|
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.Game
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
import eventDemo.contexts.game.domain.game.gameState.GameCreated
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameInit
|
import eventDemo.contexts.game.domain.game.gameState.GameInit
|
||||||
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
import eventDemo.libs.eventSource.eventStore.VersionConflictException
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
interface GameRepository {
|
interface GameRepository {
|
||||||
fun get(id: GameId): Game?
|
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
|
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.CardIsPlayedEvent
|
||||||
import eventDemo.contexts.game.domain.events.DrawFilledWithDiscardEvent
|
import eventDemo.contexts.game.domain.events.DrawFilledWithDiscardEvent
|
||||||
import eventDemo.contexts.game.domain.events.GameCreatedEvent
|
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.events.PlayerWinEvent
|
||||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
import eventDemo.contexts.game.domain.game.gameState.Game
|
||||||
import eventDemo.contexts.game.domain.game.gameState.GameStarted
|
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.KotlinLogging
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
|
||||||
+4
-4
@@ -1,7 +1,6 @@
|
|||||||
package eventDemo.contexts.game.application.notification
|
package eventDemo.contexts.game.application.notification
|
||||||
|
|
||||||
import eventDemo.contexts.game.application.command.handlers.GameCommandHandlerDispatcher
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Command
|
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Command
|
||||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.CurrentUserId
|
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.Game
|
||||||
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Notification
|
import eventDemo.contexts.game.application.logging.LoggingContextKeys.Notification
|
||||||
import eventDemo.contexts.game.application.logging.withLoggingContext
|
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.application.ports.GameEventBus
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
|
||||||
import eventDemo.libs.bus.Bus
|
import eventDemo.libs.bus.Bus
|
||||||
import eventDemo.libs.command.CommandUnicityChecker
|
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.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
File renamed without changes.
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.contexts.game.application.ports
|
package eventDemo.contexts.game.application.ports
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
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.EventStore
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
interface GameEventStore : EventStore<GameEvent, GameId>
|
interface GameEventStore : EventStore<GameEvent, GameId>
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eventDemo.domain.event.projection
|
package eventDemo.domain.event.projection
|
||||||
|
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameList
|
import eventDemo.shared.game.projection.GameList
|
||||||
|
|
||||||
interface GameListRepository {
|
interface GameListRepository {
|
||||||
fun getList(
|
fun getList(
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eventDemo.contexts.game.application.ports
|
package eventDemo.contexts.game.application.ports
|
||||||
|
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.projections.models.GameProjection
|
|
||||||
import eventDemo.libs.bus.Bus
|
import eventDemo.libs.bus.Bus
|
||||||
|
import eventDemo.shared.game.projection.GameProjection
|
||||||
|
|
||||||
interface GameProjectionBus : Bus<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.PlayerHaveDrawCardEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
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 =
|
fun GameList.applyEvent(event: GameEvent): GameList =
|
||||||
when (event) {
|
when (event) {
|
||||||
File renamed without changes.
+8
-8
@@ -1,15 +1,15 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.Card
|
import eventDemo.shared.game.Card
|
||||||
import eventDemo.contexts.game.domain.game.Card.Color
|
import eventDemo.shared.game.Card.Color
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An [GameEvent] to represent a played card.
|
* An [GameEvent] to represent a played card.
|
||||||
@@ -24,7 +24,7 @@ data class CardIsPlayedEvent(
|
|||||||
) : GameEvent,
|
) : GameEvent,
|
||||||
PlayerActionEvent {
|
PlayerActionEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
|
|
||||||
val theColorCard get() = if (card is Card.CardWithColor) card.color else chosenColor
|
val theColorCard get() = if (card is Card.CardWithColor) card.color else chosenColor
|
||||||
+7
-7
@@ -1,14 +1,14 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
import eventDemo.shared.game.DiscardPile
|
||||||
import eventDemo.contexts.game.domain.game.DrawPile
|
import eventDemo.shared.game.DrawPile
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the Pile are shuffled after the draw pille was empty
|
* When the Pile are shuffled after the draw pille was empty
|
||||||
@@ -21,6 +21,6 @@ class DrawFilledWithDiscardEvent(
|
|||||||
override val version: Int,
|
override val version: Int,
|
||||||
) : GameEvent {
|
) : GameEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+5
-5
@@ -1,12 +1,12 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This [GameEvent] is sent when all players are ready.
|
* This [GameEvent] is sent when all players are ready.
|
||||||
@@ -17,6 +17,6 @@ data class GameCreatedEvent(
|
|||||||
override val version: Int,
|
override val version: Int,
|
||||||
) : GameEvent {
|
) : GameEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+4
-4
@@ -1,10 +1,10 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
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.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
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+10
-10
@@ -1,17 +1,17 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.DiscardPile
|
import eventDemo.shared.game.DiscardPile
|
||||||
import eventDemo.contexts.game.domain.game.DrawPile
|
import eventDemo.shared.game.DrawPile
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.game.PlayerHand
|
||||||
import eventDemo.contexts.game.domain.game.PlayerHand
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This [GameEvent] is sent when all players are ready.
|
* This [GameEvent] is sent when all players are ready.
|
||||||
@@ -27,6 +27,6 @@ data class GameStartedEvent(
|
|||||||
override val version: Int,
|
override val version: Int,
|
||||||
) : GameEvent {
|
) : GameEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+6
-6
@@ -1,13 +1,13 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An [GameEvent] to represent a new player joining the game.
|
* 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
|
override val playerId: Player.PlayerId get() = player.id
|
||||||
|
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.game.Player
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
+8
-8
@@ -1,15 +1,15 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.Card
|
import eventDemo.shared.game.Card
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This [GameEvent] is sent when a player can play.
|
* This [GameEvent] is sent when a player can play.
|
||||||
@@ -24,6 +24,6 @@ data class PlayerHaveDrawCardEvent(
|
|||||||
) : GameEvent,
|
) : GameEvent,
|
||||||
PlayerActionEvent {
|
PlayerActionEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+7
-7
@@ -1,14 +1,14 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This [GameEvent] is sent when a player is ready.
|
* This [GameEvent] is sent when a player is ready.
|
||||||
@@ -22,6 +22,6 @@ data class PlayerReadyEvent(
|
|||||||
) : GameEvent,
|
) : GameEvent,
|
||||||
PlayerActionEvent {
|
PlayerActionEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+7
-7
@@ -1,14 +1,14 @@
|
|||||||
package eventDemo.contexts.game.domain.events
|
package eventDemo.contexts.game.domain.events
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This [GameEvent] is sent when a player is ready.
|
* This [GameEvent] is sent when a player is ready.
|
||||||
@@ -22,6 +22,6 @@ data class PlayerWinEvent(
|
|||||||
) : GameEvent,
|
) : GameEvent,
|
||||||
PlayerActionEvent {
|
PlayerActionEvent {
|
||||||
@Serializable(with = EventIdSerializer::class)
|
@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()
|
override val createdAt: Instant = Clock.System.now()
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
package eventDemo.contexts.game.domain.game.errors
|
package eventDemo.contexts.game.domain.game.errors
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
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.Deck
|
||||||
import eventDemo.contexts.game.domain.game.gameState.Game
|
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(
|
abstract class GameException(
|
||||||
message: String,
|
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.PlayerHaveDrawCardEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
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.GameException
|
||||||
import eventDemo.contexts.game.domain.game.errors.InconsistentEventVersionException
|
import eventDemo.contexts.game.domain.game.errors.InconsistentEventVersionException
|
||||||
|
import eventDemo.shared.game.PlayerList
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
sealed interface Game {
|
sealed interface Game {
|
||||||
val aggregateId: GameId
|
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.GameStartedEvent
|
||||||
import eventDemo.contexts.game.domain.events.NewPlayerEvent
|
import eventDemo.contexts.game.domain.events.NewPlayerEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerReadyEvent
|
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.AllPlayerNotReadyException
|
||||||
import eventDemo.contexts.game.domain.game.errors.DeckMissingCardsException
|
import eventDemo.contexts.game.domain.game.errors.DeckMissingCardsException
|
||||||
import eventDemo.contexts.game.domain.game.errors.NeedMorePlayersToStartGameException
|
import eventDemo.contexts.game.domain.game.errors.NeedMorePlayersToStartGameException
|
||||||
import eventDemo.contexts.game.domain.game.errors.ThePlayerIsNotInTheGameException
|
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(
|
data class GameCreated(
|
||||||
override val aggregateId: GameId,
|
override val aggregateId: GameId,
|
||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.domain.game.gameState
|
package eventDemo.contexts.game.domain.game.gameState
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
import eventDemo.contexts.game.domain.events.GameEvent
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.game.PlayerList
|
||||||
import eventDemo.contexts.game.domain.game.PlayerList
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
data class GameEnded(
|
data class GameEnded(
|
||||||
override val aggregateId: GameId,
|
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.GameCreatedEvent
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
import eventDemo.contexts.game.domain.events.GameEvent
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.PlayerList
|
||||||
import eventDemo.contexts.game.domain.game.PlayerList
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
data class GameInit(
|
data class GameInit(
|
||||||
override val aggregateId: GameId,
|
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.PlayerActionEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerHaveDrawCardEvent
|
import eventDemo.contexts.game.domain.events.PlayerHaveDrawCardEvent
|
||||||
import eventDemo.contexts.game.domain.events.PlayerWinEvent
|
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.InconsistentGameException
|
||||||
import eventDemo.contexts.game.domain.game.errors.ItsNotTheTurnException
|
import eventDemo.contexts.game.domain.game.errors.ItsNotTheTurnException
|
||||||
import eventDemo.contexts.game.domain.game.errors.TheCardHasNoColorException
|
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.ThePlayerIsNotInTheGameException
|
||||||
import eventDemo.contexts.game.domain.game.errors.ThePlayerMustPlayACardException
|
import eventDemo.contexts.game.domain.game.errors.ThePlayerMustPlayACardException
|
||||||
import eventDemo.contexts.game.domain.game.gameState.Game.Direction
|
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(
|
fun PlayerList.nextPlayerTurn(
|
||||||
lastPlayerId: Player.PlayerId,
|
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
|
package eventDemo.contexts.game.infrastructure.configuration.ktor
|
||||||
|
|
||||||
|
import eventDemo.shared.http.HttpErrorBadRequest
|
||||||
import io.ktor.http.HttpHeaders
|
import io.ktor.http.HttpHeaders
|
||||||
import io.ktor.http.HttpMethod
|
import io.ktor.http.HttpMethod
|
||||||
import io.ktor.http.HttpStatusCode
|
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.plugins.statuspages.StatusPages
|
||||||
import io.ktor.server.resources.Resources
|
import io.ktor.server.resources.Resources
|
||||||
import io.ktor.server.response.respondText
|
import io.ktor.server.response.respondText
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
fun Application.configureHttpRouting() {
|
fun Application.configureHttpRouting() {
|
||||||
install(CORS) {
|
install(CORS) {
|
||||||
@@ -38,17 +38,3 @@ fun Application.configureHttpRouting() {
|
|||||||
class BadRequestException(
|
class BadRequestException(
|
||||||
val httpError: HttpErrorBadRequest,
|
val httpError: HttpErrorBadRequest,
|
||||||
) : Exception()
|
) : 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
|
package eventDemo.contexts.game.infrastructure.configuration.ktor
|
||||||
|
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.game.Player
|
||||||
import eventDemo.contexts.game.domain.game.Player
|
import eventDemo.shared.ids.CommandId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.CommandIdSerializer
|
import eventDemo.shared.ids.EventId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.EventIdSerializer
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.GameIdSerializer
|
import eventDemo.shared.serializers.CommandIdSerializer
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.PlayerIdSerializer
|
import eventDemo.shared.serializers.EventIdSerializer
|
||||||
import eventDemo.libs.command.CommandId
|
import eventDemo.shared.serializers.GameIdSerializer
|
||||||
import eventDemo.libs.eventSource.EventId
|
import eventDemo.shared.serializers.PlayerIdSerializer
|
||||||
import eventDemo.libs.serializer.UUIDSerializer
|
import eventDemo.shared.serializers.UUIDSerializer
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
import io.ktor.server.application.Application
|
import io.ktor.server.application.Application
|
||||||
import io.ktor.server.application.install
|
import io.ktor.server.application.install
|
||||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
fun Application.configureSerialization() {
|
fun Application.configureSerialization() {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
@@ -29,7 +29,7 @@ fun defaultJsonSerializer(): Json =
|
|||||||
Json {
|
Json {
|
||||||
serializersModule =
|
serializersModule =
|
||||||
SerializersModule {
|
SerializersModule {
|
||||||
contextual(UUID::class) { UUIDSerializer }
|
contextual(Uuid::class) { UUIDSerializer }
|
||||||
contextual(GameId::class) { GameIdSerializer }
|
contextual(GameId::class) { GameIdSerializer }
|
||||||
contextual(EventId::class) { EventIdSerializer }
|
contextual(EventId::class) { EventIdSerializer }
|
||||||
contextual(CommandId::class) { CommandIdSerializer }
|
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.application.ports.GameEventStore
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
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.EventStore
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
import eventDemo.libs.eventSource.eventStore.EventStoreInMemory
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream to publish and read the played card event.
|
* 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.application.ports.GameEventStore
|
||||||
import eventDemo.contexts.game.domain.events.GameEvent
|
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.EventStore
|
||||||
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
import eventDemo.libs.eventSource.eventStore.EventStoreInPostgresql
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import javax.sql.DataSource
|
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.GameEventStore
|
||||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
||||||
import eventDemo.contexts.game.application.projections.applyEvent
|
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.domain.event.projection.GameListRepository
|
||||||
|
import eventDemo.shared.game.projection.GameList
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package eventDemo.contexts.game.infrastructure.persistence.projections.bus
|
package eventDemo.contexts.game.infrastructure.persistence.projections.bus
|
||||||
|
|
||||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
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.Bus
|
||||||
import eventDemo.libs.bus.BusInMemory
|
import eventDemo.libs.bus.BusInMemory
|
||||||
|
import eventDemo.shared.game.projection.GameProjection
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class GameProjectionBusInMemory :
|
class GameProjectionBusInMemory :
|
||||||
+1
-1
@@ -2,9 +2,9 @@ package eventDemo.contexts.game.infrastructure.persistence.projections.bus
|
|||||||
|
|
||||||
import com.rabbitmq.client.ConnectionFactory
|
import com.rabbitmq.client.ConnectionFactory
|
||||||
import eventDemo.contexts.game.application.ports.GameProjectionBus
|
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.Bus
|
||||||
import eventDemo.libs.bus.BusInRabbitMQ
|
import eventDemo.libs.bus.BusInRabbitMQ
|
||||||
|
import eventDemo.shared.game.projection.GameProjection
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.util.UUID
|
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.eventStores.GameRepository
|
||||||
import eventDemo.contexts.game.application.notification.toNotification
|
import eventDemo.contexts.game.application.notification.toNotification
|
||||||
import eventDemo.contexts.game.application.ports.GameEventStore
|
import eventDemo.contexts.game.application.ports.GameEventStore
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.contexts.game.infrastructure.persistence.serializers.GameIdSerializer
|
import eventDemo.shared.serializers.GameIdSerializer
|
||||||
import eventDemo.sharedKernel.currentUserId
|
import eventDemo.sharedKernel.currentUserId
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.resources.Resource
|
import io.ktor.resources.Resource
|
||||||
+3
-3
@@ -1,22 +1,22 @@
|
|||||||
package eventDemo.contexts.game.infrastructure.websocket
|
package eventDemo.contexts.game.infrastructure.websocket
|
||||||
|
|
||||||
import eventDemo.contexts.game.application.channels.GameChannelsSubscriber
|
import eventDemo.contexts.game.application.channels.GameChannelsSubscriber
|
||||||
import eventDemo.contexts.game.domain.game.GameId
|
|
||||||
import eventDemo.libs.helpers.fromFrameChannel
|
import eventDemo.libs.helpers.fromFrameChannel
|
||||||
import eventDemo.libs.helpers.toObjectChannel
|
import eventDemo.libs.helpers.toObjectChannel
|
||||||
|
import eventDemo.shared.ids.GameId
|
||||||
import eventDemo.sharedKernel.currentUserId
|
import eventDemo.sharedKernel.currentUserId
|
||||||
import io.ktor.server.auth.authenticate
|
import io.ktor.server.auth.authenticate
|
||||||
import io.ktor.server.routing.Route
|
import io.ktor.server.routing.Route
|
||||||
import io.ktor.server.websocket.webSocket
|
import io.ktor.server.websocket.webSocket
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
@DelicateCoroutinesApi
|
@DelicateCoroutinesApi
|
||||||
fun Route.gameWebSocket(channelSubscriber: GameChannelsSubscriber) {
|
fun Route.gameWebSocket(channelSubscriber: GameChannelsSubscriber) {
|
||||||
authenticate {
|
authenticate {
|
||||||
webSocket("/games/{id}") {
|
webSocket("/games/{id}") {
|
||||||
channelSubscriber.subscribePlayerToGameChannels(
|
channelSubscriber.subscribePlayerToGameChannels(
|
||||||
gameId = GameId(UUID.fromString(call.parameters["id"]!!)),
|
gameId = GameId(Uuid.parse(call.parameters["id"]!!)),
|
||||||
userId = call.currentUserId,
|
userId = call.currentUserId,
|
||||||
incomingCommandChannel = toObjectChannel(incoming),
|
incomingCommandChannel = toObjectChannel(incoming),
|
||||||
sendNotificationChannel = fromFrameChannel(outgoing),
|
sendNotificationChannel = fromFrameChannel(outgoing),
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
@@ -1,5 +1,7 @@
|
|||||||
package eventDemo.libs.command
|
package eventDemo.libs.command
|
||||||
|
|
||||||
|
import eventDemo.shared.command.Command
|
||||||
|
import eventDemo.shared.ids.CommandId
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
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
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
|
||||||
interface EventStore<E : Event<ID>, ID : AggregateId> {
|
interface EventStore<E : Event<ID>, ID : AggregateId> {
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.libs.eventSource.eventStore
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.ConcurrentMap
|
import java.util.concurrent.ConcurrentMap
|
||||||
|
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.libs.eventSource.eventStore
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
|
||||||
class EventStoreInPostgresql<E : Event<ID>, ID : AggregateId>(
|
class EventStoreInPostgresql<E : Event<ID>, ID : AggregateId>(
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.libs.eventSource.eventStore
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package eventDemo.libs.eventSource.eventStore
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import java.util.Queue
|
import java.util.Queue
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
+7
-6
@@ -1,12 +1,13 @@
|
|||||||
package eventDemo.libs.eventSource.eventStore
|
package eventDemo.libs.eventSource.eventStore
|
||||||
|
|
||||||
import eventDemo.libs.eventSource.AggregateId
|
|
||||||
import eventDemo.libs.eventSource.Event
|
import eventDemo.libs.eventSource.Event
|
||||||
|
import eventDemo.shared.ids.AggregateId
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import io.github.oshai.kotlinlogging.withLoggingContext
|
import io.github.oshai.kotlinlogging.withLoggingContext
|
||||||
import org.postgresql.util.PGobject
|
import org.postgresql.util.PGobject
|
||||||
import org.postgresql.util.PSQLException
|
import org.postgresql.util.PSQLException
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
import kotlin.uuid.toJavaUuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An In-Memory implementation of an event stream.
|
* An In-Memory implementation of an event stream.
|
||||||
@@ -39,8 +40,8 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
|||||||
on conflict (id) do nothing
|
on conflict (id) do nothing
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
).use {
|
).use {
|
||||||
it.setObject(1, event.eventId.id)
|
it.setObject(1, event.eventId.id.toJavaUuid())
|
||||||
it.setObject(2, event.aggregateId.id)
|
it.setObject(2, event.aggregateId.id.toJavaUuid())
|
||||||
it.setInt(3, event.version)
|
it.setInt(3, event.version)
|
||||||
it.setObject(4, PGJsonb(objectToString(event)))
|
it.setObject(4, PGJsonb(objectToString(event)))
|
||||||
it.executeUpdate()
|
it.executeUpdate()
|
||||||
@@ -69,7 +70,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
|||||||
order by version asc
|
order by version asc
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
).use {
|
).use {
|
||||||
it.setObject(1, aggregateId.id)
|
it.setObject(1, aggregateId.id.toJavaUuid())
|
||||||
it.executeQuery().use { resultSet ->
|
it.executeQuery().use { resultSet ->
|
||||||
buildSet {
|
buildSet {
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
@@ -95,7 +96,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
|||||||
order by version asc
|
order by version asc
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
).use {
|
).use {
|
||||||
it.setObject(1, aggregateId.id)
|
it.setObject(1, aggregateId.id.toJavaUuid())
|
||||||
it.executeQuery().use { resultSet ->
|
it.executeQuery().use { resultSet ->
|
||||||
resultSet.next()
|
resultSet.next()
|
||||||
}
|
}
|
||||||
@@ -116,7 +117,7 @@ class EventStreamInPostgresql<E : Event<ID>, ID : AggregateId>(
|
|||||||
).use { stmt ->
|
).use { stmt ->
|
||||||
stmt.setInt(1, version.first)
|
stmt.setInt(1, version.first)
|
||||||
stmt.setInt(2, version.last)
|
stmt.setInt(2, version.last)
|
||||||
stmt.setObject(3, aggregateId.id)
|
stmt.setObject(3, aggregateId.id.toJavaUuid())
|
||||||
stmt.executeQuery().use { resultSet ->
|
stmt.executeQuery().use { resultSet ->
|
||||||
buildSet {
|
buildSet {
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-2
@@ -1,12 +1,13 @@
|
|||||||
package eventDemo.sharedKernel
|
package eventDemo.sharedKernel
|
||||||
|
|
||||||
|
import eventDemo.shared.ids.UserId
|
||||||
import io.ktor.server.application.ApplicationCall
|
import io.ktor.server.application.ApplicationCall
|
||||||
import io.ktor.server.auth.jwt.JWTPrincipal
|
import io.ktor.server.auth.jwt.JWTPrincipal
|
||||||
import io.ktor.server.auth.principal
|
import io.ktor.server.auth.principal
|
||||||
import java.util.UUID
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
internal val ApplicationCall.currentUserId: UserId
|
internal val ApplicationCall.currentUserId: UserId
|
||||||
get() =
|
get() =
|
||||||
principal<JWTPrincipal>()!!.run {
|
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