diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b0098e7..2d20235 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "1.8.21" +kotlin = "1.9.20-Beta" kotlinx-coroutines = "1.6.4" kotlinx-serialization = "1.4.1" ktor = "2.0.1" @@ -7,7 +7,7 @@ kafka = "3.3.1" jupiter = "5.4.0" exposed = "0.41.1" kmongo = "4.8.0" -androidGradlePlugin = "8.2.0-alpha13" +androidGradlePlugin = "8.3.0-alpha05" androidComposeVersion = "1.4.0-alpha02" grpc = "1.3.0" protobuf = "3.22.0" @@ -66,6 +66,8 @@ grpc-android = { module = "io.grpc:grpc-android", version.require = "1.56.1" } protobuf-kotlin = { module = "com.google.protobuf:protobuf-kotlin", version.ref = "protobuf" } protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" } +rsocket-client = { module = "io.rsocket.kotlin:rsocket-ktor-client", version.require = "0.15.4" } + [plugins] kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 15de902..b982b3c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-rc-2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/grpc-engine/src/main/kotlin/io/timemates/api/grpc/GrpcTimeMatesRequestsEngine.kt b/grpc-engine/src/main/kotlin/io/timemates/api/grpc/GrpcTimeMatesRequestsEngine.kt index ef9f211..cdda75b 100644 --- a/grpc-engine/src/main/kotlin/io/timemates/api/grpc/GrpcTimeMatesRequestsEngine.kt +++ b/grpc-engine/src/main/kotlin/io/timemates/api/grpc/GrpcTimeMatesRequestsEngine.kt @@ -143,7 +143,7 @@ public class GrpcTimeMatesRequestsEngine( .setVerificationHash(request.verificationHash.string) .build() ).let { response -> - ConfirmAuthorizationRequest.Response( + ConfirmAuthorizationRequest.Result( isNewAccount = response.isNewAccount, authorization = response.authorization.takeIf { !response.isNewAccount } ?.let(authMapper::grpcAuthorizationToSdkAuthorization), diff --git a/grpc-engine/src/main/kotlin/io/timemates/api/grpc/mappers/AuthorizationsMapper.kt b/grpc-engine/src/main/kotlin/io/timemates/api/grpc/mappers/AuthorizationsMapper.kt index 15fc28c..a07e38a 100644 --- a/grpc-engine/src/main/kotlin/io/timemates/api/grpc/mappers/AuthorizationsMapper.kt +++ b/grpc-engine/src/main/kotlin/io/timemates/api/grpc/mappers/AuthorizationsMapper.kt @@ -2,7 +2,7 @@ package io.timemates.api.grpc.mappers import io.timemates.api.authorizations.types.AuthorizationOuterClass.Authorization import io.timemates.sdk.authorization.sessions.types.value.ClientIpAddress -import io.timemates.sdk.authorization.sessions.types.value.ClientName +import io.timemates.sdk.authorization.sessions.types.value.ApplicationName import io.timemates.sdk.authorization.sessions.types.value.ClientVersion import io.timemates.sdk.authorization.types.value.HashValue import io.timemates.sdk.common.constructor.createOrThrow @@ -31,7 +31,7 @@ internal class AuthorizationsMapper { metadata: Authorization.Metadata, ): SdkAuthorization.Metadata = with(metadata) { return@with SdkAuthorization.Metadata( - clientName = ClientName.createOrThrow(clientName), + applicationName = ApplicationName.createOrThrow(clientName), clientVersion = ClientVersion.createOrThrow(clientVersion), clientIpAddress = ClientIpAddress.createOrThrow(clientIpAddress), ) diff --git a/rsocket-engine/build.gradle.kts b/rsocket-engine/build.gradle.kts new file mode 100644 index 0000000..1421908 --- /dev/null +++ b/rsocket-engine/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.library.publish) +} + +kotlin { + jvm() + jvmToolchain(17) + + explicitApi() +} + +dependencies { + commonMainImplementation(projects.sdk) + + commonMainImplementation(libs.kotlinx.serialization) + commonMainImplementation(libs.kotlinx.datetime) + commonMainImplementation(libs.rsocket.client) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/CommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/CommandsRegistry.kt new file mode 100644 index 0000000..ce6cd4e --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/CommandsRegistry.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket + +import io.timemates.api.rsocket.authorizations.commands.authorizations +import io.timemates.api.rsocket.common.commands.rSocketCommands +import io.timemates.api.rsocket.files.commands.files +import io.timemates.api.rsocket.timers.commands.timers +import io.timemates.api.rsocket.users.commands.users + +/** + * Registry for RSocket commands used in the TimeMates application. + * + * The [rSocketCommandsRegistry] is responsible for initializing and registering RSocket commands + * for specific TimeMates features or functionalities. + */ +internal val rSocketCommandsRegistry = rSocketCommands { + authorizations() + users() + files() + timers() +} diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/RSocketTimeMatesRequestsEngine.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/RSocketTimeMatesRequestsEngine.kt new file mode 100644 index 0000000..b099d39 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/RSocketTimeMatesRequestsEngine.kt @@ -0,0 +1,58 @@ +package io.timemates.api.rsocket + +import io.ktor.client.HttpClient +import io.rsocket.kotlin.ExperimentalMetadataApi +import io.rsocket.kotlin.RSocket +import io.rsocket.kotlin.ktor.client.rSocket +import io.rsocket.kotlin.metadata.RoutingMetadata +import io.rsocket.kotlin.metadata.compositeMetadata +import io.rsocket.kotlin.payload.buildPayload +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.common.metadata.AuthorizationMetadata +import io.timemates.api.rsocket.common.serialization.decodeFromJson +import io.timemates.api.rsocket.common.serialization.encodeToJson +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.sdk.common.engine.TimeMatesRequestsEngine +import io.timemates.sdk.common.exceptions.UnsupportedException +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest +import io.timemates.sdk.timers.requests.EditTimerRequest +import io.timemates.sdk.timers.requests.GetTimerRequest +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.async +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.serializer +import io.timemates.api.rsocket.timers.requests.RSocketEditTimerRequest as RSocketEditTimerRequest +import io.timemates.api.rsocket.timers.requests.RSocketGetTimerRequest as RSocketGetTimerRequest + +/** + * Represents an engine for making requests using RSocket. + * + * @property client An instance of [HttpClient] for making HTTP requests. + * @param endpoint The RSocket endpoint URL. Defaults to "wss://api.timemates.io/v0/rsocket". + * @param coroutineScope A [CoroutineScope] tied to the RSocket lifecycle. + */ +public class RSocketTimeMatesRequestsEngine private constructor( + private val client: HttpClient, + endpoint: String = "wss://api.timemates.io/v0/rsocket", + coroutineScope: CoroutineScope, +) : TimeMatesRequestsEngine { + public companion object { + public const val API_VERSION: Int = 1 + } + + private val rSocket = coroutineScope.async(start = CoroutineStart.LAZY) { + client.rSocket(endpoint) + } + + override suspend fun execute( + request: TimeMatesRequest, + ): Result = runCatching { + val rSocket = rSocket.await() + return@runCatching rSocketCommandsRegistry.execute(rSocket, request) + ?: throw UnsupportedException("This type of request is not supported in RSocket engine.") + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/AuthorizationCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/AuthorizationCommandsRegistry.kt new file mode 100644 index 0000000..c7820d2 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/AuthorizationCommandsRegistry.kt @@ -0,0 +1,23 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.sdk.authorization.email.requests.ConfigureNewAccountRequest +import io.timemates.sdk.authorization.email.requests.ConfirmAuthorizationRequest +import io.timemates.sdk.authorization.email.requests.StartAuthorizationRequest +import io.timemates.sdk.authorization.sessions.requests.GetAuthorizationSessionsRequest +import io.timemates.sdk.authorization.sessions.requests.RenewAuthorizationRequest +import io.timemates.sdk.authorization.sessions.requests.TerminateCurrentAuthorizationSessionRequest +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi + +/** + * The commands that is connected to the authorization feature. + */ +@OptIn(ExperimentalTimeMatesApi::class) +internal fun RSocketCommandsBuilderScope.authorizations() { + StartAuthorizationCommand associatedWith StartAuthorizationRequest + ConfirmAuthorizationCommand associatedWith ConfirmAuthorizationRequest + ConfigureNewAccountCommand associatedWith ConfigureNewAccountRequest + GetAuthorizationSessionsCommand associatedWith GetAuthorizationSessionsRequest + TerminateCurrentAuthorizationCommand associatedWith TerminateCurrentAuthorizationSessionRequest + RenewAuthorizationCommand associatedWith RenewAuthorizationRequest +} diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfigureNewAccountCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfigureNewAccountCommand.kt new file mode 100644 index 0000000..5345bcd --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfigureNewAccountCommand.kt @@ -0,0 +1,25 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.authorizations.types.sdk +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.email.requests.ConfigureNewAccountRequest +import io.timemates.api.rsocket.authorizations.requests.ConfigureAccountRequest as RSocketConfigureAccountRequest + +internal object ConfigureNewAccountCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: ConfigureNewAccountRequest): ConfigureNewAccountRequest.Result { + return rSocket.requestResponse( + route = "authorizations.account.configure", + data = RSocketConfigureAccountRequest( + verificationHash = input.verificationHash.string, + name = input.name.string, + description = input.description?.string, + ) + ).let { result -> + ConfigureNewAccountRequest.Result( + authorization = result.authorization.sdk() + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfirmAuthorizationCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfirmAuthorizationCommand.kt new file mode 100644 index 0000000..bdfebe8 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/ConfirmAuthorizationCommand.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.authorizations.types.sdk +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.email.requests.ConfirmAuthorizationRequest +import io.timemates.api.rsocket.authorizations.requests.ConfirmAuthorizationRequest as RSocketConfirmAuthorizationRequest + +internal object ConfirmAuthorizationCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: ConfirmAuthorizationRequest): ConfirmAuthorizationRequest.Result { + return rSocket.requestResponse( + route = "authorizations.email.confirm", + data = RSocketConfirmAuthorizationRequest( + input.verificationHash.string, input.confirmationCode.string + ) + ).let { result -> + ConfirmAuthorizationRequest.Result( + isNewAccount = result.isNewAccount, + authorization = result.authorization?.sdk(), + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/GetAuthorizationSessionsCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/GetAuthorizationSessionsCommand.kt new file mode 100644 index 0000000..33b0b84 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/GetAuthorizationSessionsCommand.kt @@ -0,0 +1,28 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.authorizations.requests.GetAuthorizationsRequest +import io.timemates.api.rsocket.authorizations.types.SerializableAuthorization +import io.timemates.api.rsocket.authorizations.types.sdk +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.sessions.requests.GetAuthorizationSessionsRequest +import io.timemates.sdk.authorization.sessions.types.Authorization +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.pagination.Page +import io.timemates.sdk.common.pagination.PageToken + +internal object GetAuthorizationSessionsCommand : RSocketCommand> { + override suspend fun execute(rSocket: RSocket, input: GetAuthorizationSessionsRequest): Page { + return rSocket.requestResponse( + route = "authorizations.list", + data = GetAuthorizationsRequest(input.nextPageToken?.string), + accessHash = input.accessHash.string, + ).let { result -> + Page( + results = result.list.map(SerializableAuthorization::sdk), + nextPageToken = result.nextPageToken?.let { PageToken.createOrThrow(it) } + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/RenewAuthorizationCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/RenewAuthorizationCommand.kt new file mode 100644 index 0000000..ba7bbfd --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/RenewAuthorizationCommand.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.sessions.requests.RenewAuthorizationRequest +import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.api.rsocket.authorizations.requests.RenewAuthorizationRequest as RSocketRenewAuthorizationRequest + +@OptIn(ExperimentalTimeMatesApi::class) +internal object RenewAuthorizationCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: RenewAuthorizationRequest): RenewAuthorizationRequest.Result { + return rSocket.requestResponse( + route = "authorizations.renew", + data = RSocketRenewAuthorizationRequest(input.refreshHash.string), + ).let { result -> + RenewAuthorizationRequest.Result( + AccessHash.createOrThrow(result.accessHash) + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/StartAuthorizationCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/StartAuthorizationCommand.kt new file mode 100644 index 0000000..8394eb8 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/StartAuthorizationCommand.kt @@ -0,0 +1,33 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.authorizations.types.serializable +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.email.requests.StartAuthorizationRequest +import io.timemates.sdk.authorization.email.types.value.VerificationHash +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.types.value.Count +import kotlinx.datetime.Instant +import io.timemates.api.rsocket.authorizations.requests.StartAuthorizationRequest as RSocketStartAuthorizationRequest + +internal object StartAuthorizationCommand : RSocketCommand { + override suspend fun execute( + rSocket: RSocket, + input: StartAuthorizationRequest, + ): StartAuthorizationRequest.Result { + return rSocket.requestResponse( + route = "authorizations.email.start", + data = RSocketStartAuthorizationRequest( + input.emailAddress.string, + input.metadata.serializable(), + ) + ).let { result -> + StartAuthorizationRequest.Result( + verificationHash = VerificationHash.createOrThrow(result.verificationHash), + attempts = Count.createOrThrow(result.attempts), + expiresAt = Instant.fromEpochMilliseconds(result.expiresAt), + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/TerminateCurrentAuthorizationCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/TerminateCurrentAuthorizationCommand.kt new file mode 100644 index 0000000..c99e1f9 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/commands/TerminateCurrentAuthorizationCommand.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.authorizations.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.authorizations.requests.TerminateAuthorizationRequest +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.authorization.sessions.requests.TerminateCurrentAuthorizationSessionRequest +import io.timemates.sdk.common.types.Empty + +internal object TerminateCurrentAuthorizationCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: TerminateCurrentAuthorizationSessionRequest): Empty { + return rSocket.requestResponse( + route = "authorizations.terminate", + data = TerminateAuthorizationRequest.Current, + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfigureAccountRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfigureAccountRequest.kt new file mode 100644 index 0000000..8f0a72a --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfigureAccountRequest.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.authorizations.types.SerializableAuthorization +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class ConfigureAccountRequest( + val verificationHash: String, + val name: String, + val description: String?, +) : RSocketRequest { + @Serializable + data class Result( + val authorization: SerializableAuthorization, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfirmAuthorizationRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfirmAuthorizationRequest.kt new file mode 100644 index 0000000..a8fb57d --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/ConfirmAuthorizationRequest.kt @@ -0,0 +1,16 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.authorizations.types.SerializableAuthorization +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class ConfirmAuthorizationRequest( + val verificationHash: String, + val confirmationCode: String, +) : RSocketRequest { + data class Response( + val isNewAccount: Boolean, + val authorization: SerializableAuthorization?, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/GetAuthorizationsRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/GetAuthorizationsRequest.kt new file mode 100644 index 0000000..f191ad6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/GetAuthorizationsRequest.kt @@ -0,0 +1,14 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.authorizations.types.SerializableAuthorization +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class GetAuthorizationsRequest( + val pageToken: String? = null, +) : RSocketRequest { + + @Serializable + data class Result(val list: List, val nextPageToken: String?) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/RenewAuthorizationRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/RenewAuthorizationRequest.kt new file mode 100644 index 0000000..1656599 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/RenewAuthorizationRequest.kt @@ -0,0 +1,12 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RenewAuthorizationRequest( + val refreshHash: String, +) : RSocketRequest { + @Serializable + data class Result(val accessHash: String) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/StartAuthorizationRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/StartAuthorizationRequest.kt new file mode 100644 index 0000000..8904e26 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/StartAuthorizationRequest.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.authorizations.types.SerializableAuthMetadata +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class StartAuthorizationRequest( + val email: String, + val clientMetadata: SerializableAuthMetadata, +) : RSocketRequest { + @Serializable + data class Result( + val verificationHash: String, + val expiresAt: Long, + val attempts: Int, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/TerminateAuthorizationRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/TerminateAuthorizationRequest.kt new file mode 100644 index 0000000..5bcdba0 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/requests/TerminateAuthorizationRequest.kt @@ -0,0 +1,15 @@ +package io.timemates.api.rsocket.authorizations.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal sealed class TerminateAuthorizationRequest : RSocketRequest { + /** + * This type of termination request terminates authorization with which + * user has sent termination request. + */ + @SerialName("current") + data object Current : TerminateAuthorizationRequest() +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthMetadata.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthMetadata.kt new file mode 100644 index 0000000..e9c7ac5 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthMetadata.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.authorizations.types + +import io.timemates.sdk.authorization.sessions.types.Authorization +import kotlinx.serialization.Serializable + +@Serializable +internal data class SerializableAuthMetadata( + val applicationName: String, + val clientVersion: String, + val clientIpAddress: String?, +) + +internal fun Authorization.Metadata.serializable(): SerializableAuthMetadata = SerializableAuthMetadata( + applicationName = applicationName.string, + clientVersion = clientVersion.string, + clientIpAddress = clientIpAddress.string, +) \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorization.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorization.kt new file mode 100644 index 0000000..b3eabca --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorization.kt @@ -0,0 +1,19 @@ +package io.timemates.api.rsocket.authorizations.types + +import io.timemates.sdk.authorization.sessions.types.Authorization +import kotlinx.serialization.Serializable + +@Serializable +internal data class SerializableAuthorization( + val userId: Long, + val accessHash: String, + val refreshAccessHash: String, + val scopes: List, + // todo expiresAt for refresh hash + val expiresAt: Long, + val createdAt: Long, + val clientMetadata: SerializableAuthMetadata, +) + +// todo expiresAt for refresh hash +internal fun SerializableAuthorization.sdk(): Authorization = TODO() \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorizationScope.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorizationScope.kt new file mode 100644 index 0000000..3840ab7 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/authorizations/types/SerializableAuthorizationScope.kt @@ -0,0 +1,34 @@ +package io.timemates.api.rsocket.authorizations.types + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal sealed interface SerializableAuthorizationScope { + @SerialName("super") + data object All : SerializableAuthorizationScope + + @SerialName("auth:read") + data object AuthRead : SerializableAuthorizationScope + + @SerialName("auth:write") + data object AuthWrite : SerializableAuthorizationScope + + @SerialName("users:read") + data object UsersRead : SerializableAuthorizationScope + + @SerialName("users:write") + data object UsersWrite : SerializableAuthorizationScope + + @SerialName("timers:read") + data object TimersRead : SerializableAuthorizationScope + + @SerialName("timers:write") + data object TimersWrite : SerializableAuthorizationScope + + @SerialName("files:read") + data object FilesRead : SerializableAuthorizationScope + + @SerialName("files:write") + data object FilesWrite : SerializableAuthorizationScope +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommand.kt new file mode 100644 index 0000000..5c2f583 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommand.kt @@ -0,0 +1,26 @@ +package io.timemates.api.rsocket.common.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest + +/** + * An interface representing a command that can be executed via an RSocket connection. + * + * This interface is used to decouple logic by accepting an SDK entity of type [T] + * and converting it into the engine's entity type [R] within the implementation. + * + * @param T The type of the SDK entity that serves as the command's input. + * @param R The type of the engine's entity that represents the command's result. + */ +internal interface RSocketCommand, R : TimeMatesEntity> { + /** + * Executes the command using the provided RSocket connection and input of type [T]. + * + * @param rSocket The RSocket connection over which the command will be executed. + * @param input The SDK entity representing the command's input. + * @return The engine's entity representing the result of executing the command. + * @throws RSocketException if there is an issue with the RSocket communication. + */ + suspend fun execute(rSocket: RSocket, input: T): R +} diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommands.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommands.kt new file mode 100644 index 0000000..a235cc4 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommands.kt @@ -0,0 +1,38 @@ +package io.timemates.api.rsocket.common.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest + +/** + * An inline class that encapsulates a set of RSocket commands for executing TimeMates requests. + * + * The [RSocketCommands] class allows you to execute TimeMates requests using the provided RSocket + * instance. It maintains a map of commands associated with request keys, which are used to look up + * the appropriate command for a given request. + * + * @param commands A map of request keys to RSocket command implementations. + */ +@JvmInline +internal value class RSocketCommands( + private val commands: Map, RSocketCommand<*, *>>, +) { + /** + * Executes a TimeMates request using the specified RSocket instance. + * + * This function looks up the appropriate RSocket command based on the request's [requestKey] + * and executes it with the provided RSocket and request object. + * + * @param T The specific type of the TimeMates request. + * @param R The type of the response expected from the request. + * @param rSocket The RSocket instance to use for executing the request. + * @param request The TimeMates request to execute. + */ + suspend inline fun , R : TimeMatesEntity> execute( + rSocket: RSocket, + request: T, + ): R? { + @Suppress("UNCHECKED_CAST") + return (commands[request.requestKey] as? RSocketCommand)?.execute(rSocket, request) + } +} diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommandsBuilderScope.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommandsBuilderScope.kt new file mode 100644 index 0000000..2889876 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/commands/RSocketCommandsBuilderScope.kt @@ -0,0 +1,37 @@ +package io.timemates.api.rsocket.common.commands + +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest + +@RSocketCommandsDsl +@JvmInline +internal value class RSocketCommandsBuilderScope( + private val commands: MutableMap, RSocketCommand<*, *>> = + mutableMapOf(), +) { + fun , R : TimeMatesEntity> associate( + key: TimeMatesRequest.Key, + command: RSocketCommand, + ) { + commands += key to command + } + + + infix fun , R : TimeMatesEntity> RSocketCommand.associatedWith( + key: TimeMatesRequest.Key, + ) { + associate(key, this) + } + + fun build(): RSocketCommands = RSocketCommands(commands) +} + +@DslMarker +internal annotation class RSocketCommandsDsl + +@RSocketCommandsDsl +internal inline fun rSocketCommands( + block: RSocketCommandsBuilderScope.() -> Unit, +): RSocketCommands { + return RSocketCommandsBuilderScope().apply(block).build() +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/ext/RSocketExt.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/ext/RSocketExt.kt new file mode 100644 index 0000000..853e9dd --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/ext/RSocketExt.kt @@ -0,0 +1,84 @@ +package io.timemates.api.rsocket.common.ext + +import io.rsocket.kotlin.ExperimentalMetadataApi +import io.rsocket.kotlin.RSocket +import io.rsocket.kotlin.metadata.RoutingMetadata +import io.rsocket.kotlin.metadata.compositeMetadata +import io.rsocket.kotlin.payload.Payload +import io.rsocket.kotlin.payload.buildPayload +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.common.metadata.AuthorizationMetadata +import io.timemates.api.rsocket.common.serialization.decodeFromJson +import io.timemates.api.rsocket.common.serialization.encodeToJson +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.serializer + +internal suspend inline fun , reified R> RSocket.requestResponse( + route: String, + data: T, + accessHash: String? = null, +): R = requestResponse(route, serializer(), serializer(), data, accessHash) + +internal suspend inline fun > RSocket.fireAndForget( + route: String, + data: T, + accessHash: String? = null, +): Unit = fireAndForget(route, serializer(), data, accessHash) + +internal inline fun , reified R> RSocket.requestStream( + route: String, + data: T, + accessHash: String? = null, +): Flow = requestStream(route, serializer(), serializer(), data, accessHash) + +internal suspend fun RSocket.requestResponse( + route: String, + dataSerStrategy: SerializationStrategy, + resultDeSerStrategy: DeserializationStrategy, + data: T, + accessHash: String? = null, +): R { + val payload = createPayload(route, data, dataSerStrategy, accessHash) + return requestResponse(payload).decodeFromJson(resultDeSerStrategy) +} + +internal fun RSocket.requestStream( + route: String, + dataSerStrategy: SerializationStrategy, + resultDeSerStrategy: DeserializationStrategy, + data: T, + accessHash: String? = null, +): Flow { + val payload = createPayload(route, data, dataSerStrategy, accessHash) + return requestStream(payload).map { it.decodeFromJson(resultDeSerStrategy) } +} + +internal suspend fun RSocket.fireAndForget( + route: String, + dataSerStrategy: SerializationStrategy, + data: T, + accessHash: String? = null, +) { + val payload = createPayload(route, data, dataSerStrategy, accessHash) + return fireAndForget(payload) +} + +@OptIn(ExperimentalMetadataApi::class) +private fun createPayload( + route: String, + data: T, + dataSerStrategy: SerializationStrategy, + accessHash: String?, +): Payload { + return buildPayload { + compositeMetadata { + add(RoutingMetadata(route)) + if (accessHash != null) + add(AuthorizationMetadata(accessHash)) + } + data(data.encodeToJson(dataSerStrategy)) + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/markers/RSocketRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/markers/RSocketRequest.kt new file mode 100644 index 0000000..1a545ea --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/markers/RSocketRequest.kt @@ -0,0 +1,8 @@ +package io.timemates.api.rsocket.common.markers + +/** + * Interface-marker for all RSocket requests. + * + * @param R response type of the request. + */ +internal interface RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/metadata/AuthorizationMetadata.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/metadata/AuthorizationMetadata.kt new file mode 100644 index 0000000..38401da --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/metadata/AuthorizationMetadata.kt @@ -0,0 +1,37 @@ +package io.timemates.api.rsocket.common.metadata + +import io.ktor.utils.io.core.BytePacketBuilder +import io.ktor.utils.io.core.ByteReadPacket +import io.ktor.utils.io.core.internal.ChunkBuffer +import io.ktor.utils.io.core.isNotEmpty +import io.ktor.utils.io.core.readTextExactBytes +import io.ktor.utils.io.core.writeFully +import io.ktor.utils.io.pool.ObjectPool +import io.rsocket.kotlin.ExperimentalMetadataApi +import io.rsocket.kotlin.core.MimeType +import io.rsocket.kotlin.core.WellKnownMimeType +import io.rsocket.kotlin.metadata.Metadata +import io.rsocket.kotlin.metadata.MetadataReader + +@ExperimentalMetadataApi +internal class AuthorizationMetadata(val authorization: String) : Metadata { + + override val mimeType: MimeType get() = Reader.mimeType + + override fun BytePacketBuilder.writeSelf() { + val bytes = authorization.encodeToByteArray() + writeByte(bytes.size.toByte()) + writeFully(bytes) + } + + override fun close(): Unit = Unit + + companion object Reader : MetadataReader { + override val mimeType: MimeType get() = WellKnownMimeType.MessageRSocketRouting + override fun ByteReadPacket.read(pool: ObjectPool): AuthorizationMetadata { + return AuthorizationMetadata( + readTextExactBytes(readByte().toInt() and 0xFF) + ) + } + } +} diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/serialization/JsonExt.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/serialization/JsonExt.kt new file mode 100644 index 0000000..ee8b7ff --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/common/serialization/JsonExt.kt @@ -0,0 +1,23 @@ +package io.timemates.api.rsocket.common.serialization + +import io.ktor.utils.io.core.ByteReadPacket +import io.ktor.utils.io.streams.inputStream +import io.rsocket.kotlin.payload.Payload +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream + +private val json = Json { + ignoreUnknownKeys = true +} + +internal fun T.encodeToJson(serializationStrategy: SerializationStrategy): ByteReadPacket { + return ByteReadPacket(json.encodeToString(serializationStrategy, this).encodeToByteArray()) +} + +@OptIn(ExperimentalSerializationApi::class) +internal fun Payload.decodeFromJson(deserializationStrategy: DeserializationStrategy): T { + return json.decodeFromStream(deserializationStrategy, data.inputStream()) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/FilesCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/FilesCommandsRegistry.kt new file mode 100644 index 0000000..5b18e95 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/FilesCommandsRegistry.kt @@ -0,0 +1,11 @@ +package io.timemates.api.rsocket.files.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.sdk.files.requests.GetFileBytesRequest + +/** + * RSocket commands related to timers. + */ +internal fun RSocketCommandsBuilderScope.files() { + GetFileCommand associatedWith GetFileBytesRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/GetFileCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/GetFileCommand.kt new file mode 100644 index 0000000..9115fb6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/commands/GetFileCommand.kt @@ -0,0 +1,22 @@ +package io.timemates.api.rsocket.files.commands + +import io.rsocket.kotlin.RSocket +import io.rsocket.kotlin.payload.buildPayload +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.serialization.encodeToJson +import io.timemates.api.rsocket.files.requests.GetFileRequest +import io.timemates.sdk.files.requests.GetFileBytesRequest +import kotlinx.serialization.serializer + +internal object GetFileCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: GetFileBytesRequest): GetFileBytesRequest.Result { + return rSocket.requestResponse( + buildPayload { + data(GetFileRequest(input.fileId.string).encodeToJson(serializer())) + } + ).let { result -> +// GetFileBytesRequest.Result(result.data) + TODO() + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/GetFileRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/GetFileRequest.kt new file mode 100644 index 0000000..8858a0f --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/GetFileRequest.kt @@ -0,0 +1,19 @@ +package io.timemates.api.rsocket.files.requests + +import io.timemates.api.rsocket.files.types.SerializableFileType +import kotlinx.serialization.Serializable + +@Serializable +internal data class GetFileRequest( + val fileId: String, +) { + @Serializable + sealed interface Response { + data class Metadata( + val fileType: SerializableFileType, + ) : Response + + @JvmInline + value class Chunk(val bytes: ByteArray) : Response + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/UploadFileRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/UploadFileRequest.kt new file mode 100644 index 0000000..ccc8809 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/requests/UploadFileRequest.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.files.requests + +import io.timemates.api.rsocket.files.types.SerializableFileType +import kotlinx.coroutines.flow.Flow +import kotlinx.serialization.Serializable + +@Serializable +internal data class UploadFileRequest( + val fileType: SerializableFileType, + val bytes: Flow, +) { + @Serializable + data class Metadata(val fileName: String, val fileType: SerializableFileType) + + @Serializable + data class Response(val fileId: String) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFile.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFile.kt new file mode 100644 index 0000000..9a48d2b --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFile.kt @@ -0,0 +1,15 @@ +package io.timemates.api.rsocket.files.types + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal sealed class SerializableFile { + abstract val fileId: String + + /** + * File with image. + */ + @SerialName("image") + data class Image(override val fileId: String) : SerializableFile() +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFileType.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFileType.kt new file mode 100644 index 0000000..0c6f69e --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/files/types/SerializableFileType.kt @@ -0,0 +1,10 @@ +package io.timemates.api.rsocket.files.types + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal enum class SerializableFileType { + @SerialName("image") + IMAGE, +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/CreateTimerCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/CreateTimerCommand.kt new file mode 100644 index 0000000..0c615fd --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/CreateTimerCommand.kt @@ -0,0 +1,26 @@ +package io.timemates.api.rsocket.timers.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.types.serializable +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.types.value.TimerId +import io.timemates.api.rsocket.timers.requests.RSocketCreateTimerRequest as RSocketCreateTimerRequest + +internal object CreateTimerCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: CreateTimerRequest): CreateTimerRequest.Result { + return rSocket.requestResponse( + route = "timers.create", + data = RSocketCreateTimerRequest( + name = input.name.string, + description = input.description.string, + settings = input.settings.serializable() + ), + accessHash = input.accessHash.string, + ).let { result -> + CreateTimerRequest.Result(TimerId.createOrThrow(result.timerId)) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/EditTimerCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/EditTimerCommand.kt new file mode 100644 index 0000000..4c9e078 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/EditTimerCommand.kt @@ -0,0 +1,22 @@ +package io.timemates.api.rsocket.timers.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.requests.EditTimerRequest +import io.timemates.api.rsocket.timers.requests.RSocketEditTimerRequest as RSocketEditTimerRequest + +internal object EditTimerCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: EditTimerRequest): Empty { + return rSocket.requestResponse( + route = "timers.edit", + data = RSocketEditTimerRequest( + timerId = input.timerId.long, + name = input.name?.string, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetTimerCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetTimerCommand.kt new file mode 100644 index 0000000..4c8ad12 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetTimerCommand.kt @@ -0,0 +1,27 @@ +package io.timemates.api.rsocket.timers.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.requests.RSocketGetTimerRequest +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.api.rsocket.timers.types.serializable +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.requests.GetTimerRequest +import io.timemates.sdk.timers.types.value.TimerId +import io.timemates.api.rsocket.timers.requests.RSocketCreateTimerRequest as RSocketCreateTimerRequest + +internal object GetTimerCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: GetTimerRequest): GetTimerRequest.Result { + return rSocket.requestResponse( + route = "timers.get", + data = RSocketGetTimerRequest( + timerId = input.timerId.long, + ), + accessHash = input.accessHash.string, + ).let { result -> + GetTimerRequest.Result(result.timer.sdk()) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetUserTimersCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetUserTimersCommand.kt new file mode 100644 index 0000000..54b983a --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/GetUserTimersCommand.kt @@ -0,0 +1,30 @@ +package io.timemates.api.rsocket.timers.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.requests.RSocketGetUserTimersRequest +import io.timemates.api.rsocket.timers.types.SerializableTimer +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.pagination.Page +import io.timemates.sdk.common.pagination.PageToken +import io.timemates.sdk.timers.requests.GetUserTimersRequest +import io.timemates.sdk.timers.types.Timer + +internal object GetUserTimersCommand : RSocketCommand> { + override suspend fun execute(rSocket: RSocket, input: GetUserTimersRequest): Page { + return rSocket.requestResponse( + route = "timers.user.list", + data = RSocketGetUserTimersRequest( + pageToken = input.pageToken?.string, + ), + accessHash = input.accessHash.string, + ).let { result -> + Page( + results = result.list.map(SerializableTimer::sdk), + nextPageToken = result.nextPageToken?.let { PageToken.createOrThrow(it) }, + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/RemoveTimerCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/RemoveTimerCommand.kt new file mode 100644 index 0000000..8a19ffb --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/RemoveTimerCommand.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.timers.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.requests.RemoveTimerRequest +import io.timemates.api.rsocket.timers.requests.RSocketDeleteTimerRequest as RSocketDeleteTimerRequest + +internal object RemoveTimerCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: RemoveTimerRequest): Empty { + return rSocket.requestResponse( + route = "timers.delete", + data = RSocketDeleteTimerRequest(input.timerId.long), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/TimersCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/TimersCommandsRegistry.kt new file mode 100644 index 0000000..ad3f892 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/commands/TimersCommandsRegistry.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.timers.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.api.rsocket.timers.members.commands.timerMembers +import io.timemates.api.rsocket.timers.sessions.commands.timerSessions +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.requests.EditTimerRequest +import io.timemates.sdk.timers.requests.GetTimerRequest +import io.timemates.sdk.timers.requests.GetUserTimersRequest +import io.timemates.sdk.timers.requests.RemoveTimerRequest + +/** + * RSocket commands related to timers. + */ +internal fun RSocketCommandsBuilderScope.timers() { + timerMembers() + timerSessions() + + CreateTimerCommand associatedWith CreateTimerRequest + EditTimerCommand associatedWith EditTimerRequest + GetTimerCommand associatedWith GetTimerRequest + RemoveTimerCommand associatedWith RemoveTimerRequest + GetUserTimersCommand associatedWith GetUserTimersRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/GetTimerMembersCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/GetTimerMembersCommand.kt new file mode 100644 index 0000000..f7a1cdb --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/GetTimerMembersCommand.kt @@ -0,0 +1,36 @@ +package io.timemates.api.rsocket.timers.members.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.members.requests.RSocketGetMembersListRequest +import io.timemates.api.rsocket.timers.requests.RSocketGetUserTimersRequest +import io.timemates.api.rsocket.timers.types.SerializableTimer +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.api.rsocket.users.types.SerializableUser +import io.timemates.api.rsocket.users.types.sdk +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.pagination.Page +import io.timemates.sdk.common.pagination.PageToken +import io.timemates.sdk.timers.members.requests.GetMembersRequest +import io.timemates.sdk.timers.requests.GetUserTimersRequest +import io.timemates.sdk.timers.types.Timer +import io.timemates.sdk.users.profile.types.User + +internal object GetTimerMembersCommand : RSocketCommand> { + override suspend fun execute(rSocket: RSocket, input: GetMembersRequest): Page { + return rSocket.requestResponse( + route = "timers.user.list", + data = RSocketGetMembersListRequest( + timerId = input.timerId.long, + pageToken = input.pageToken?.string, + ), + accessHash = input.accessHash.string, + ).let { result -> + Page( + results = result.list.map(SerializableUser::sdk), + nextPageToken = result.nextPageToken?.let { PageToken.createOrThrow(it) }, + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/KickTimerMemberCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/KickTimerMemberCommand.kt new file mode 100644 index 0000000..758cc86 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/KickTimerMemberCommand.kt @@ -0,0 +1,19 @@ +package io.timemates.api.rsocket.timers.members.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.members.requests.KickMemberRequest +import io.timemates.sdk.timers.requests.RemoveTimerRequest +import io.timemates.api.rsocket.timers.requests.RSocketDeleteTimerRequest as RSocketDeleteTimerRequest + +internal object KickTimerMemberCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: KickMemberRequest): Empty { + return rSocket.requestResponse( + route = "timers.members.kick", + data = RSocketDeleteTimerRequest(input.timerId.long), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/TimerMembersCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/TimerMembersCommandsRegistry.kt new file mode 100644 index 0000000..e21024f --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/commands/TimerMembersCommandsRegistry.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket.timers.members.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.api.rsocket.timers.members.invites.commands.timerMemberInvites +import io.timemates.sdk.timers.members.requests.GetMembersRequest +import io.timemates.sdk.timers.members.requests.KickMemberRequest +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.requests.EditTimerRequest +import io.timemates.sdk.timers.requests.GetTimerRequest +import io.timemates.sdk.timers.requests.RemoveTimerRequest + +/** + * RSocket commands related to timer members. + */ +internal fun RSocketCommandsBuilderScope.timerMembers() { + timerMemberInvites() + + GetTimerMembersCommand associatedWith GetMembersRequest + KickTimerMemberCommand associatedWith KickMemberRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/CreateInviteCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/CreateInviteCommand.kt new file mode 100644 index 0000000..b552478 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/CreateInviteCommand.kt @@ -0,0 +1,28 @@ +package io.timemates.api.rsocket.timers.members.invites.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.members.invites.requests.RSocketCreateInviteRequest +import io.timemates.api.rsocket.timers.types.serializable +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.timers.members.invites.requests.CreateInviteRequest +import io.timemates.sdk.timers.members.invites.types.value.InviteCode +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.types.value.TimerId +import io.timemates.api.rsocket.timers.requests.RSocketCreateTimerRequest as RSocketCreateTimerRequest + +internal object CreateInviteCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: CreateInviteRequest): CreateInviteRequest.Result { + return rSocket.requestResponse( + route = "timers.members.invites.create", + data = RSocketCreateInviteRequest( + timerId = input.timerId.long, + maxJoiners = input.maxJoinersCount.int, + ), + accessHash = input.accessHash.string, + ).let { result -> + CreateInviteRequest.Result(InviteCode.createOrThrow(result.inviteCode)) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/GetInvitesCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/GetInvitesCommand.kt new file mode 100644 index 0000000..9ae809f --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/GetInvitesCommand.kt @@ -0,0 +1,31 @@ +package io.timemates.api.rsocket.timers.members.invites.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.members.invites.requests.RSocketGetInvitesListRequest +import io.timemates.api.rsocket.timers.members.invites.types.SerializableInvite +import io.timemates.api.rsocket.timers.members.invites.types.sdk +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.pagination.Page +import io.timemates.sdk.common.pagination.PageToken +import io.timemates.sdk.timers.members.invites.requests.GetInvitesRequest +import io.timemates.sdk.timers.members.invites.types.Invite + +internal object GetInvitesCommand : RSocketCommand> { + override suspend fun execute(rSocket: RSocket, input: GetInvitesRequest): Page { + return rSocket.requestResponse( + route = "timers.user.list", + data = RSocketGetInvitesListRequest( + timerId = input.timerId.long, + pageToken = input.pageToken?.string, + ), + accessHash = input.accessHash.string, + ).let { result -> + Page( + results = result.invites.map(SerializableInvite::sdk), + nextPageToken = result.nextPageToken?.let { PageToken.createOrThrow(it) }, + ) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/JoinTimerByCodeCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/JoinTimerByCodeCommand.kt new file mode 100644 index 0000000..99348f8 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/JoinTimerByCodeCommand.kt @@ -0,0 +1,27 @@ +package io.timemates.api.rsocket.timers.members.invites.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.members.invites.requests.RSocketCreateInviteRequest +import io.timemates.api.rsocket.timers.members.invites.requests.RSocketJoinTimerByCodeRequest +import io.timemates.api.rsocket.timers.types.serializable +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.timers.members.invites.requests.JoinTimerByCodeRequest +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.types.value.TimerId +import io.timemates.api.rsocket.timers.requests.RSocketCreateTimerRequest as RSocketCreateTimerRequest + +internal object JoinTimerByCodeCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: JoinTimerByCodeRequest): JoinTimerByCodeRequest.Result { + return rSocket.requestResponse( + route = "timers.create", + data = RSocketJoinTimerByCodeRequest( + code = input.code.string, + ), + accessHash = input.accessHash.string, + ).let { result -> + JoinTimerByCodeRequest.Result(TimerId.createOrThrow(result.timerId)) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/RemoveInviteCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/RemoveInviteCommand.kt new file mode 100644 index 0000000..5de7b45 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/RemoveInviteCommand.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.timers.members.invites.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.members.invites.requests.RSocketRemoveInviteRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.members.invites.requests.RemoveInviteRequest +import io.timemates.sdk.timers.members.requests.KickMemberRequest +import io.timemates.sdk.timers.requests.RemoveTimerRequest +import io.timemates.api.rsocket.timers.requests.RSocketDeleteTimerRequest as RSocketDeleteTimerRequest + +internal object RemoveInviteCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: RemoveInviteRequest): Empty { + return rSocket.requestResponse( + route = "timers.members.kick", + data = RSocketRemoveInviteRequest( + timerId = input.timerId.long, + code = input.inviteCode.string, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/TimerMembersCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/TimerMembersCommandsRegistry.kt new file mode 100644 index 0000000..ad64e2a --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/commands/TimerMembersCommandsRegistry.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.timers.members.invites.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.sdk.timers.members.invites.requests.CreateInviteRequest +import io.timemates.sdk.timers.members.invites.requests.GetInvitesRequest +import io.timemates.sdk.timers.members.invites.requests.JoinTimerByCodeRequest +import io.timemates.sdk.timers.members.invites.requests.RemoveInviteRequest + +/** + * RSocket commands related to timer members. + */ +internal fun RSocketCommandsBuilderScope.timerMemberInvites() { + CreateInviteCommand associatedWith CreateInviteRequest + GetInvitesCommand associatedWith GetInvitesRequest + JoinTimerByCodeCommand associatedWith JoinTimerByCodeRequest + RemoveInviteCommand associatedWith RemoveInviteRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketCreateInviteRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketCreateInviteRequest.kt new file mode 100644 index 0000000..5b39f57 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketCreateInviteRequest.kt @@ -0,0 +1,13 @@ +package io.timemates.api.rsocket.timers.members.invites.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketCreateInviteRequest( + val timerId: Long, + val maxJoiners: Int, +) : RSocketRequest { + @Serializable + data class Result(val inviteCode: String) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketGetInvitesListRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketGetInvitesListRequest.kt new file mode 100644 index 0000000..bac07b2 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketGetInvitesListRequest.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.timers.members.invites.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.members.invites.types.SerializableInvite +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketGetInvitesListRequest( + val timerId: Long, + val pageToken: String? = null, +) : RSocketRequest { + @Serializable + data class Result( + val invites: List, + val nextPageToken: String? = null, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketJoinTimerByCodeRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketJoinTimerByCodeRequest.kt new file mode 100644 index 0000000..ccbded7 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketJoinTimerByCodeRequest.kt @@ -0,0 +1,12 @@ +package io.timemates.api.rsocket.timers.members.invites.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketJoinTimerByCodeRequest( + val code: String, +) : RSocketRequest { + @Serializable + data class Result(val timerId: Long) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketRemoveInviteRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketRemoveInviteRequest.kt new file mode 100644 index 0000000..90e0380 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/requests/RSocketRemoveInviteRequest.kt @@ -0,0 +1,10 @@ +package io.timemates.api.rsocket.timers.members.invites.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketRemoveInviteRequest( + val timerId: Long, + val code: String, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/types/SerializableInvite.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/types/SerializableInvite.kt new file mode 100644 index 0000000..1333e4b --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/invites/types/SerializableInvite.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.timers.members.invites.types + +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.types.value.Count +import io.timemates.sdk.timers.members.invites.types.Invite +import io.timemates.sdk.timers.members.invites.types.value.InviteCode +import kotlinx.datetime.Instant +import kotlinx.serialization.Serializable + +@Serializable +internal data class SerializableInvite( + val timerId: Long, + val code: String, + val creationTime: Long, + val limit: Int, +) + +internal fun SerializableInvite.sdk(): Invite { + return Invite( + inviteCode = InviteCode.createOrThrow(code), + creationTime = Instant.fromEpochMilliseconds(creationTime), + limit = Count.createOrThrow(limit), + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketGetMembersListRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketGetMembersListRequest.kt new file mode 100644 index 0000000..1383216 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketGetMembersListRequest.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.timers.members.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.users.types.SerializableUser +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketGetMembersListRequest( + val timerId: Long, + val pageToken: String? = null, +) : RSocketRequest { + @Serializable + data class Result( + val list: List, + val nextPageToken: String? = null, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketKickMemberRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketKickMemberRequest.kt new file mode 100644 index 0000000..a68a527 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/members/requests/RSocketKickMemberRequest.kt @@ -0,0 +1,6 @@ +package io.timemates.api.rsocket.timers.members.requests + +internal data class RSocketKickMemberRequest( + val timerId: Long, + val userId: Long, +) \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketCreateTimerRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketCreateTimerRequest.kt new file mode 100644 index 0000000..e4352f8 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketCreateTimerRequest.kt @@ -0,0 +1,15 @@ +package io.timemates.api.rsocket.timers.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.types.SerializableTimerSettings +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketCreateTimerRequest( + val name: String, + val description: String = "", + val settings: SerializableTimerSettings? = null, +) : RSocketRequest { + @Serializable + data class Result(val timerId: Long) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketDeleteTimerRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketDeleteTimerRequest.kt new file mode 100644 index 0000000..9b78b94 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketDeleteTimerRequest.kt @@ -0,0 +1,9 @@ +package io.timemates.api.rsocket.timers.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketDeleteTimerRequest( + val timerId: Long, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketEditTimerRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketEditTimerRequest.kt new file mode 100644 index 0000000..a526724 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketEditTimerRequest.kt @@ -0,0 +1,13 @@ +package io.timemates.api.rsocket.timers.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.types.SerializableTimerSettingsPatch +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketEditTimerRequest( + val timerId: Long, + val name: String? = null, + val description: String? = null, + val settings: SerializableTimerSettingsPatch? = null, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetTimerRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetTimerRequest.kt new file mode 100644 index 0000000..b3a91df --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetTimerRequest.kt @@ -0,0 +1,13 @@ +package io.timemates.api.rsocket.timers.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.types.SerializableTimer +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketGetTimerRequest( + val timerId: Long, +) : RSocketRequest { + @Serializable + data class Result(val timer: SerializableTimer) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetUserTimersRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetUserTimersRequest.kt new file mode 100644 index 0000000..8dbe072 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/requests/RSocketGetUserTimersRequest.kt @@ -0,0 +1,16 @@ +package io.timemates.api.rsocket.timers.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.types.SerializableTimer +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketGetUserTimersRequest( + val pageToken: String? = null, +) : RSocketRequest { + @Serializable + data class Result( + val nextPageToken: String? = null, + val list: List, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/ConfirmSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/ConfirmSessionCommand.kt new file mode 100644 index 0000000..ee7f7c1 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/ConfirmSessionCommand.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketConfirmSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.ConfirmTimerRoundRequest + +internal object ConfirmSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: ConfirmTimerRoundRequest): Empty { + return rSocket.requestResponse( + route = "timers.sessions.attendance.confirm", + data = RSocketConfirmSessionRequest, + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetCurrentSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetCurrentSessionCommand.kt new file mode 100644 index 0000000..40c1cd4 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetCurrentSessionCommand.kt @@ -0,0 +1,19 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketGetCurrentSessionRequest +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.sdk.timers.sessions.requests.GetUserCurrentSessionRequest +import io.timemates.sdk.timers.types.Timer + +internal object GetCurrentSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: GetUserCurrentSessionRequest): Timer { + return rSocket.requestResponse( + route = "timers.sessions.ping", + data = RSocketGetCurrentSessionRequest, + accessHash = input.accessHash.string, + ).timer.sdk() + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetTimerStateCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetTimerStateCommand.kt new file mode 100644 index 0000000..06cf6ec --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/GetTimerStateCommand.kt @@ -0,0 +1,32 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.common.ext.requestStream +import io.timemates.api.rsocket.timers.requests.RSocketGetTimerRequest +import io.timemates.api.rsocket.timers.sessions.requests.RSocketGetCurrentTimerStateRequest +import io.timemates.api.rsocket.timers.sessions.types.sdk +import io.timemates.api.rsocket.timers.types.sdk +import io.timemates.api.rsocket.timers.types.serializable +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.timers.requests.CreateTimerRequest +import io.timemates.sdk.timers.requests.GetTimerRequest +import io.timemates.sdk.timers.sessions.requests.GetTimerStateRequest +import io.timemates.sdk.timers.types.value.TimerId +import kotlinx.coroutines.flow.map +import io.timemates.api.rsocket.timers.requests.RSocketCreateTimerRequest as RSocketCreateTimerRequest + +internal object GetTimerStateCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: GetTimerStateRequest): GetTimerStateRequest.Result { + return rSocket.requestStream( + route = "timers.get", + data = RSocketGetCurrentTimerStateRequest( + timerId = input.timerId.long, + ), + accessHash = input.accessHash.string, + ).let { result -> + GetTimerStateRequest.Result(result.map { it.sdk() }) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/JoinSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/JoinSessionCommand.kt new file mode 100644 index 0000000..fa800a1 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/JoinSessionCommand.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketJoinSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.JoinTimerSessionRequest + +internal object JoinSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: JoinTimerSessionRequest): Empty { + return rSocket.requestResponse( + route = "timers.sessions.join", + data = RSocketJoinSessionRequest( + timerId = input.timerId.long, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/LeaveSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/LeaveSessionCommand.kt new file mode 100644 index 0000000..16b3fb7 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/LeaveSessionCommand.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketLeaveSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.LeaveTimerSessionRequest + +internal object LeaveSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: LeaveTimerSessionRequest): Empty { + return rSocket.requestResponse( + route = "timers.sessions.leave", + data = RSocketLeaveSessionRequest, + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/PingSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/PingSessionCommand.kt new file mode 100644 index 0000000..4dec5d6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/PingSessionCommand.kt @@ -0,0 +1,18 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.fireAndForget +import io.timemates.api.rsocket.timers.sessions.requests.RSocketLeaveSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.PingSessionRequest + +internal object PingSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: PingSessionRequest): Empty { + return rSocket.fireAndForget( + route = "timers.sessions.ping", + data = RSocketLeaveSessionRequest, + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StartSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StartSessionCommand.kt new file mode 100644 index 0000000..9eba5f2 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StartSessionCommand.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketStartSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.StartTimerRequest + +internal object StartSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: StartTimerRequest): Empty { + return rSocket.requestResponse( + route = "timers.sessions.start", + data = RSocketStartSessionRequest( + timerId = input.timerId.long, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StopSessionCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StopSessionCommand.kt new file mode 100644 index 0000000..94f0dd6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/StopSessionCommand.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.timers.sessions.requests.RSocketStopSessionRequest +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.timers.sessions.requests.StopTimerRequest + +internal object StopSessionCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: StopTimerRequest): Empty { + return rSocket.requestResponse( + route = "timers.sessions.start", + data = RSocketStopSessionRequest( + timerId = input.timerId.long, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/TimerSessionsCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/TimerSessionsCommandsRegistry.kt new file mode 100644 index 0000000..bd38fb0 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/commands/TimerSessionsCommandsRegistry.kt @@ -0,0 +1,25 @@ +package io.timemates.api.rsocket.timers.sessions.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.sdk.timers.sessions.requests.ConfirmTimerRoundRequest +import io.timemates.sdk.timers.sessions.requests.GetTimerStateRequest +import io.timemates.sdk.timers.sessions.requests.GetUserCurrentSessionRequest +import io.timemates.sdk.timers.sessions.requests.JoinTimerSessionRequest +import io.timemates.sdk.timers.sessions.requests.LeaveTimerSessionRequest +import io.timemates.sdk.timers.sessions.requests.PingSessionRequest +import io.timemates.sdk.timers.sessions.requests.StartTimerRequest +import io.timemates.sdk.timers.sessions.requests.StopTimerRequest + +/** + * RSocket commands related to timer members. + */ +internal fun RSocketCommandsBuilderScope.timerSessions() { + ConfirmSessionCommand associatedWith ConfirmTimerRoundRequest + LeaveSessionCommand associatedWith LeaveTimerSessionRequest + PingSessionCommand associatedWith PingSessionRequest + GetCurrentSessionCommand associatedWith GetUserCurrentSessionRequest + StartSessionCommand associatedWith StartTimerRequest + StopSessionCommand associatedWith StopTimerRequest + JoinSessionCommand associatedWith JoinTimerSessionRequest + GetTimerStateCommand associatedWith GetTimerStateRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketConfirmSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketConfirmSessionRequest.kt new file mode 100644 index 0000000..13a7f10 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketConfirmSessionRequest.kt @@ -0,0 +1,7 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data object RSocketConfirmSessionRequest : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentSessionRequest.kt new file mode 100644 index 0000000..e23b1d8 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentSessionRequest.kt @@ -0,0 +1,11 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.types.SerializableTimer +import kotlinx.serialization.Serializable + +@Serializable +internal data object RSocketGetCurrentSessionRequest : RSocketRequest { + @Serializable + data class Result(val timer: SerializableTimer) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentTimerStateRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentTimerStateRequest.kt new file mode 100644 index 0000000..70deed1 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketGetCurrentTimerStateRequest.kt @@ -0,0 +1,10 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.timers.sessions.types.SerializableTimerState +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketGetCurrentTimerStateRequest( + val timerId: Long, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketJoinSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketJoinSessionRequest.kt new file mode 100644 index 0000000..fbf2afd --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketJoinSessionRequest.kt @@ -0,0 +1,9 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketJoinSessionRequest( + val timerId: Long, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketLeaveSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketLeaveSessionRequest.kt new file mode 100644 index 0000000..0bf9d29 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketLeaveSessionRequest.kt @@ -0,0 +1,7 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data object RSocketLeaveSessionRequest : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketPingCurrentSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketPingCurrentSessionRequest.kt new file mode 100644 index 0000000..61d7c66 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketPingCurrentSessionRequest.kt @@ -0,0 +1,6 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import kotlinx.serialization.Serializable + +@Serializable +internal data object RSocketPingCurrentSessionRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStartSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStartSessionRequest.kt new file mode 100644 index 0000000..bbf6bb9 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStartSessionRequest.kt @@ -0,0 +1,9 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketStartSessionRequest( + val timerId: Long, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStopSessionRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStopSessionRequest.kt new file mode 100644 index 0000000..3d7c22d --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/requests/RSocketStopSessionRequest.kt @@ -0,0 +1,9 @@ +package io.timemates.api.rsocket.timers.sessions.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class RSocketStopSessionRequest( + val timerId: Long, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/types/SerializableTimerState.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/types/SerializableTimerState.kt new file mode 100644 index 0000000..3856e86 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/sessions/types/SerializableTimerState.kt @@ -0,0 +1,62 @@ +package io.timemates.api.rsocket.timers.sessions.types + +import io.timemates.sdk.timers.types.Timer +import kotlinx.datetime.Instant +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Represents current timer state. + * @see SDK Source + */ +@Serializable +internal sealed class SerializableTimerState { + abstract val endsAt: Long? + abstract val publishTime: Long + + @SerialName("inactive") + data class Inactive(override val publishTime: Long) : SerializableTimerState() { + override val endsAt: Long? get() = null + } + + @SerialName("pause") + data class Pause(override val publishTime: Long) : SerializableTimerState() { + override val endsAt: Long? get() = null + } + + @SerialName("running") + data class Running(override val endsAt: Long, override val publishTime: Long) : SerializableTimerState() + + @SerialName("rest") + data class Rest(override val endsAt: Long, override val publishTime: Long) : SerializableTimerState() + + @SerialName("confirmation") + data class Confirmation(override val endsAt: Long, override val publishTime: Long) : SerializableTimerState() +} + +internal fun SerializableTimerState.sdk(): Timer.State { + val endsAt = endsAt?.let { Instant.fromEpochMilliseconds(it) } + val publishTime = Instant.fromEpochMilliseconds(publishTime) + + return when (this) { + is SerializableTimerState.Confirmation -> + Timer.State.ConfirmationWaiting( + endsAt = endsAt!!, + publishTime = publishTime, + ) + is SerializableTimerState.Inactive -> Timer.State.Inactive( + publishTime = publishTime, + ) + is SerializableTimerState.Pause -> Timer.State.Paused( + publishTime = publishTime, + ) + is SerializableTimerState.Rest -> Timer.State.Rest( + endsAt = endsAt!!, + publishTime = publishTime, + ) + is SerializableTimerState.Running -> Timer.State.Running( + endsAt = endsAt!!, + publishTime = publishTime, + ) + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimer.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimer.kt new file mode 100644 index 0000000..02c45a6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimer.kt @@ -0,0 +1,33 @@ +package io.timemates.api.rsocket.timers.types + +import io.timemates.api.rsocket.timers.sessions.types.SerializableTimerState +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.types.value.Count +import io.timemates.sdk.timers.types.Timer +import io.timemates.sdk.timers.types.value.TimerDescription +import io.timemates.sdk.timers.types.value.TimerId +import io.timemates.sdk.timers.types.value.TimerName +import io.timemates.sdk.users.profile.types.value.UserId +import kotlinx.serialization.Serializable + +@Serializable +internal data class SerializableTimer( + val id: Long, + val name: String, + val description: String, + val ownerId: Long, + val settings: SerializableTimerSettings, + val membersCount: Int, + val state: SerializableTimerState, +) + +internal fun SerializableTimer.sdk(): Timer { + return Timer( + timerId = TimerId.createOrThrow(id), + name = TimerName.createOrThrow(name), + description = TimerDescription.createOrThrow(description), + ownerId = UserId.createOrThrow(ownerId), + membersCount = Count.createOrThrow(membersCount), + settings = settings.sdk(), + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettings.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettings.kt new file mode 100644 index 0000000..b4a410f --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettings.kt @@ -0,0 +1,42 @@ +package io.timemates.api.rsocket.timers.types + +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.common.types.value.Count +import io.timemates.sdk.timers.types.TimerSettings +import kotlinx.serialization.Serializable +import kotlin.time.Duration + +@Serializable +internal data class SerializableTimerSettings( + val workTime: Duration, + val restTime: Duration, + val bigRestTime: Duration, + val bigRestEnabled: Boolean, + val bigRestPer: Int, + val isEveryoneCanPause: Boolean, + val isConfirmationRequired: Boolean, +) + +internal fun TimerSettings.serializable(): SerializableTimerSettings { + return SerializableTimerSettings( + workTime = workTime, + restTime = restTime, + bigRestTime = bigRestTime, + bigRestEnabled = bigRestEnabled, + bigRestPer = bigRestPer.int, + isEveryoneCanPause = isEveryoneCanPause, + isConfirmationRequired = isConfirmationRequired, + ) +} + +internal fun SerializableTimerSettings.sdk(): TimerSettings { + return TimerSettings( + workTime = workTime, + restTime = restTime, + bigRestTime = bigRestTime, + bigRestEnabled = bigRestEnabled, + bigRestPer = Count.createOrThrow(bigRestPer), + isEveryoneCanPause = isEveryoneCanPause, + isConfirmationRequired = isConfirmationRequired, + ) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettingsPatch.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettingsPatch.kt new file mode 100644 index 0000000..cefb805 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/timers/types/SerializableTimerSettingsPatch.kt @@ -0,0 +1,15 @@ +package io.timemates.api.rsocket.timers.types + +import kotlinx.serialization.Serializable +import kotlin.time.Duration + +@Serializable +internal data class SerializableTimerSettingsPatch( + val workTime: Duration? = null, + val restTime: Duration? = null, + val bigRestTime: Duration? = null, + val bigRestEnabled: Boolean? = null, + val bigRestPer: Int? = null, + val isEveryoneCanPause: Boolean? = null, + val isConfirmationRequired: Boolean? = null, +) \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditEmailCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditEmailCommand.kt new file mode 100644 index 0000000..9de520a --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditEmailCommand.kt @@ -0,0 +1,24 @@ +package io.timemates.api.rsocket.users.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.users.requests.EditUserProfileRequest +import io.timemates.api.rsocket.users.types.serializable +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.users.profile.requests.EditProfileRequest +import io.timemates.sdk.users.settings.requests.EditEmailRequest + +@OptIn(ExperimentalTimeMatesApi::class) +internal object EditEmailCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: EditEmailRequest): Empty { + return rSocket.requestResponse( + route = "users.email.edit", + data = io.timemates.api.rsocket.users.requests.EditEmailRequest( + email = input.newEmail.string, + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditProfileCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditProfileCommand.kt new file mode 100644 index 0000000..556a5b5 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/EditProfileCommand.kt @@ -0,0 +1,23 @@ +package io.timemates.api.rsocket.users.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.users.requests.EditUserProfileRequest +import io.timemates.api.rsocket.users.types.serializable +import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.users.profile.requests.EditProfileRequest + +internal object EditProfileCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: EditProfileRequest): Empty { + return rSocket.requestResponse( + route = "users.profile.edit", + data = EditUserProfileRequest( + name = input.name?.string, + description = input.description?.string, + avatar = input.avatar?.serializable(), + ), + accessHash = input.accessHash.string, + ).let { _ -> Empty } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/GetUsersCommand.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/GetUsersCommand.kt new file mode 100644 index 0000000..02c6e93 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/GetUsersCommand.kt @@ -0,0 +1,20 @@ +package io.timemates.api.rsocket.users.commands + +import io.rsocket.kotlin.RSocket +import io.timemates.api.rsocket.common.commands.RSocketCommand +import io.timemates.api.rsocket.common.ext.requestResponse +import io.timemates.api.rsocket.users.types.SerializableUser +import io.timemates.api.rsocket.users.types.sdk +import io.timemates.sdk.users.profile.requests.GetUsersRequest +import io.timemates.api.rsocket.users.requests.GetUsersRequest as RSocketGetUsersRequest + +internal object GetUsersCommand : RSocketCommand { + override suspend fun execute(rSocket: RSocket, input: GetUsersRequest): GetUsersRequest.Result { + return rSocket.requestResponse( + route = "users.profile.list", + data = RSocketGetUsersRequest(ids = input.users.map { it.long }) + ).let { result -> + GetUsersRequest.Result(result.list.map(SerializableUser::sdk)) + } + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/UsersCommandsRegistry.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/UsersCommandsRegistry.kt new file mode 100644 index 0000000..89ee76c --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/commands/UsersCommandsRegistry.kt @@ -0,0 +1,17 @@ +package io.timemates.api.rsocket.users.commands + +import io.timemates.api.rsocket.common.commands.RSocketCommandsBuilderScope +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi +import io.timemates.sdk.users.profile.requests.EditProfileRequest +import io.timemates.sdk.users.profile.requests.GetUsersRequest +import io.timemates.sdk.users.settings.requests.EditEmailRequest + +/** + * RSocket commands related to user operations. + */ +@OptIn(ExperimentalTimeMatesApi::class) +internal fun RSocketCommandsBuilderScope.users() { + EditProfileCommand associatedWith EditProfileRequest + GetUsersCommand associatedWith GetUsersRequest + EditEmailCommand associatedWith EditEmailRequest +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditEmailRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditEmailRequest.kt new file mode 100644 index 0000000..7a10739 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditEmailRequest.kt @@ -0,0 +1,9 @@ +package io.timemates.api.rsocket.users.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import kotlinx.serialization.Serializable + +@Serializable +internal data class EditEmailRequest( + val email: String, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditUserProfileRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditUserProfileRequest.kt new file mode 100644 index 0000000..405e4a1 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/EditUserProfileRequest.kt @@ -0,0 +1,12 @@ +package io.timemates.api.rsocket.users.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.users.types.SerializableAvatar +import kotlinx.serialization.Serializable + +@Serializable +internal data class EditUserProfileRequest( + val avatar: SerializableAvatar?, + val name: String?, + val description: String?, +) : RSocketRequest \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/GetUsersRequest.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/GetUsersRequest.kt new file mode 100644 index 0000000..ae4a011 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/requests/GetUsersRequest.kt @@ -0,0 +1,13 @@ +package io.timemates.api.rsocket.users.requests + +import io.timemates.api.rsocket.common.markers.RSocketRequest +import io.timemates.api.rsocket.users.types.SerializableUser +import kotlinx.serialization.Serializable + +@Serializable +internal data class GetUsersRequest( + val ids: List, +) : RSocketRequest { + @Serializable + data class Result(val list: List) +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableAvatar.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableAvatar.kt new file mode 100644 index 0000000..92497a6 --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableAvatar.kt @@ -0,0 +1,29 @@ +package io.timemates.api.rsocket.users.types + +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.users.profile.types.Avatar +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal sealed interface SerializableAvatar { + @SerialName("gravatar") + data class Gravatar(val gravatarId: String) : SerializableAvatar + + @SerialName("timemates") + data class TimeMates(val fileId: String) : SerializableAvatar +} + +internal fun Avatar.serializable(): SerializableAvatar { + return when (this) { + is Avatar.GravatarId -> SerializableAvatar.Gravatar(string) + is Avatar.FileId -> SerializableAvatar.TimeMates(string) + } +} + +internal fun SerializableAvatar.sdk(): Avatar { + return when (this) { + is SerializableAvatar.TimeMates -> Avatar.GravatarId.createOrThrow(fileId) + is SerializableAvatar.Gravatar -> Avatar.FileId.createOrThrow(gravatarId) + } +} \ No newline at end of file diff --git a/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableUser.kt b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableUser.kt new file mode 100644 index 0000000..858073b --- /dev/null +++ b/rsocket-engine/src/commonMain/kotlin/io/timemates/api/rsocket/users/types/SerializableUser.kt @@ -0,0 +1,28 @@ +package io.timemates.api.rsocket.users.types + +import io.timemates.sdk.common.constructor.createOrThrow +import io.timemates.sdk.users.profile.types.User +import io.timemates.sdk.users.profile.types.value.EmailAddress +import io.timemates.sdk.users.profile.types.value.UserDescription +import io.timemates.sdk.users.profile.types.value.UserId +import io.timemates.sdk.users.profile.types.value.UserName +import kotlinx.serialization.Serializable + +@Serializable +internal data class SerializableUser( + val id: Long, + val name: String, + val emailAddress: String?, + val description: String?, + val avatar: SerializableAvatar?, +) + +internal fun SerializableUser.sdk(): User { + return User( + id = UserId.createOrThrow(id), + name = UserName.createOrThrow(name), + description = description?.let { UserDescription.createOrThrow(it) }, + emailAddress = emailAddress?.let { EmailAddress.createOrThrow(it) }, + avatar = avatar?.sdk() + ) +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/EmailAuthorizationApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/EmailAuthorizationApi.kt index 011a199..3a85a35 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/EmailAuthorizationApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/EmailAuthorizationApi.kt @@ -4,6 +4,7 @@ import io.timemates.sdk.authorization.email.requests.ConfigureNewAccountRequest import io.timemates.sdk.authorization.email.requests.ConfirmAuthorizationRequest import io.timemates.sdk.authorization.email.requests.StartAuthorizationRequest import io.timemates.sdk.authorization.email.types.value.VerificationHash +import io.timemates.sdk.authorization.sessions.types.Authorization import io.timemates.sdk.authorization.sessions.types.value.ConfirmationCode import io.timemates.sdk.common.engine.TimeMatesRequestsEngine import io.timemates.sdk.users.profile.types.value.EmailAddress @@ -21,8 +22,12 @@ public class EmailAuthorizationApi(private val engine: TimeMatesRequestsEngine) * * @see confirm */ - public suspend fun authorize(emailAddress: EmailAddress): Result { - return engine.execute(StartAuthorizationRequest(emailAddress)).map { it.verificationHash } + public suspend fun authorize( + emailAddress: EmailAddress, + metadata: Authorization.Metadata, + ): Result { + return engine.execute(StartAuthorizationRequest(emailAddress, metadata)) + .map { it.verificationHash } } /** @@ -36,7 +41,7 @@ public class EmailAuthorizationApi(private val engine: TimeMatesRequestsEngine) public suspend fun confirm( verificationHash: VerificationHash, confirmationCode: ConfirmationCode, - ): Result { + ): Result { return engine.execute(ConfirmAuthorizationRequest(verificationHash, confirmationCode)) } diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfigureNewAccountRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfigureNewAccountRequest.kt index 8a11ec5..cb4f74c 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfigureNewAccountRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfigureNewAccountRequest.kt @@ -10,7 +10,12 @@ import io.timemates.sdk.users.profile.types.value.UserName public data class ConfigureNewAccountRequest( val verificationHash: VerificationHash, val name: UserName, - val description: UserDescription, + val description: UserDescription?, ) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + public data class Result(val authorization: Authorization) : TimeMatesEntity() + + override val requestKey: Key + get() = Key } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfirmAuthorizationRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfirmAuthorizationRequest.kt index 6e9d3a4..3296000 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfirmAuthorizationRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/ConfirmAuthorizationRequest.kt @@ -1,17 +1,22 @@ package io.timemates.sdk.authorization.email.requests +import io.timemates.sdk.authorization.email.types.value.VerificationHash import io.timemates.sdk.authorization.sessions.types.Authorization import io.timemates.sdk.authorization.sessions.types.value.ConfirmationCode -import io.timemates.sdk.authorization.email.types.value.VerificationHash import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest public data class ConfirmAuthorizationRequest( val verificationHash: VerificationHash, val confirmationCode: ConfirmationCode, -) : TimeMatesRequest() { - public data class Response( +) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + public data class Result( val isNewAccount: Boolean, val authorization: Authorization?, ) : TimeMatesEntity() + + override val requestKey: Key + get() = Key } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/StartAuthorizationRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/StartAuthorizationRequest.kt index 7c103d4..cf1411b 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/StartAuthorizationRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/email/requests/StartAuthorizationRequest.kt @@ -1,18 +1,24 @@ package io.timemates.sdk.authorization.email.requests -import io.timemates.sdk.users.profile.types.value.EmailAddress import io.timemates.sdk.authorization.email.types.value.VerificationHash +import io.timemates.sdk.authorization.sessions.types.Authorization import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.common.types.value.Count +import io.timemates.sdk.users.profile.types.value.EmailAddress import kotlinx.datetime.Instant public data class StartAuthorizationRequest( - val emailAddress: EmailAddress + val emailAddress: EmailAddress, + val metadata: Authorization.Metadata, ) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + public data class Result( val verificationHash: VerificationHash, val attempts: Count, val expiresAt: Instant, ) : TimeMatesEntity() + + override val requestKey: Key get() = Key } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/AuthorizedSessionsApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/AuthorizedSessionsApi.kt index 6150783..147bf8e 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/AuthorizedSessionsApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/AuthorizedSessionsApi.kt @@ -16,9 +16,6 @@ import io.timemates.sdk.common.providers.AccessHashProvider import io.timemates.sdk.common.providers.getAsResult import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.value.Count -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/GetAuthorizationSessionsRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/GetAuthorizationSessionsRequest.kt index d727df4..96d605b 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/GetAuthorizationSessionsRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/GetAuthorizationSessionsRequest.kt @@ -4,10 +4,15 @@ import io.timemates.sdk.authorization.sessions.types.Authorization import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.pagination.Page import io.timemates.sdk.common.pagination.PageToken -import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesRequest public data class GetAuthorizationSessionsRequest( val nextPageToken: PageToken?, - val accessHash: AccessHash, -) : TimeMatesRequest>() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest>() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key + get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/RenewAuthorizationRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/RenewAuthorizationRequest.kt new file mode 100644 index 0000000..b9875b6 --- /dev/null +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/RenewAuthorizationRequest.kt @@ -0,0 +1,22 @@ +package io.timemates.sdk.authorization.sessions.requests + +import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.authorization.types.value.HashValue +import io.timemates.sdk.common.annotations.ApiStatus +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest + +@ExperimentalTimeMatesApi(status = ApiStatus.IN_PROGRESS) +public data class RenewAuthorizationRequest( + val refreshHash: HashValue, +) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + @ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) + public data class Result( + val accessHash: AccessHash, + ) : TimeMatesEntity() + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/TerminateCurrentAuthorizationSessionRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/TerminateCurrentAuthorizationSessionRequest.kt index 2406b88..5eee55f 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/TerminateCurrentAuthorizationSessionRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/requests/TerminateCurrentAuthorizationSessionRequest.kt @@ -1,9 +1,14 @@ package io.timemates.sdk.authorization.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest public data class TerminateCurrentAuthorizationSessionRequest( - val accessHash: AccessHash -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/Authorization.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/Authorization.kt index 57260ac..d10796a 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/Authorization.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/Authorization.kt @@ -1,7 +1,7 @@ package io.timemates.sdk.authorization.sessions.types +import io.timemates.sdk.authorization.sessions.types.value.ApplicationName import io.timemates.sdk.authorization.sessions.types.value.ClientIpAddress -import io.timemates.sdk.authorization.sessions.types.value.ClientName import io.timemates.sdk.authorization.sessions.types.value.ClientVersion import io.timemates.sdk.authorization.types.value.HashValue import io.timemates.sdk.common.types.TimeMatesEntity @@ -19,7 +19,7 @@ public data class Authorization( ) : TimeMatesEntity() public data class Metadata( - val clientName: ClientName, + val applicationName: ApplicationName, val clientVersion: ClientVersion, val clientIpAddress: ClientIpAddress, ) : TimeMatesEntity() diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ApplicationName.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ApplicationName.kt new file mode 100644 index 0000000..aad89c8 --- /dev/null +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ApplicationName.kt @@ -0,0 +1,12 @@ +package io.timemates.sdk.authorization.sessions.types.value + +import io.timemates.sdk.common.constructor.Factory + +@JvmInline +public value class ApplicationName private constructor(public val string: String) { + public companion object : Factory() { + override fun create(input: String): Result { + return Result.success(ApplicationName(input)) + } + } +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ClientName.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ClientName.kt deleted file mode 100644 index f2eb3ca..0000000 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/authorization/sessions/types/value/ClientName.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.timemates.sdk.authorization.sessions.types.value - -import io.timemates.sdk.common.constructor.Factory - -@JvmInline -public value class ClientName private constructor(public val string: String) { - public companion object : Factory() { - override fun create(input: String): Result { - return Result.success(ClientName(input)) - } - } -} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalTimeMatesApi.kt similarity index 81% rename from sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalApi.kt rename to sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalTimeMatesApi.kt index a920340..a45ed91 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/annotations/ExperimentalTimeMatesApi.kt @@ -4,7 +4,7 @@ package io.timemates.sdk.common.annotations * Annotation used to indicate that a given SDK API is experimental. */ @RequiresOptIn(message = "Given SDK API is experimental", level = RequiresOptIn.Level.ERROR) -public annotation class ExperimentalApi(val status: ApiStatus) +public annotation class ExperimentalTimeMatesApi(val status: ApiStatus) public enum class ApiStatus { PROTOTYPE, diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/exceptions/handler/SafeExceptionResult.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/exceptions/handler/SafeExceptionResult.kt index 352fdc8..416c51c 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/exceptions/handler/SafeExceptionResult.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/exceptions/handler/SafeExceptionResult.kt @@ -1,12 +1,16 @@ -@file:OptIn(InternalApi::class, ExperimentalApi::class) +@file:OptIn(InternalApi::class, ExperimentalTimeMatesApi::class) package io.timemates.sdk.common.exceptions.handler import io.timemates.sdk.common.annotations.ApiStatus -import io.timemates.sdk.common.annotations.ExperimentalApi +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi import io.timemates.sdk.common.annotations.InternalApi +import io.timemates.sdk.common.exceptions.NotFoundException +import io.timemates.sdk.common.exceptions.TimeMatesException +import io.timemates.sdk.common.exceptions.TooManyRequestsException +import io.timemates.sdk.common.exceptions.UnauthorizedException +import io.timemates.sdk.common.exceptions.UnavailableException import io.timemates.sdk.common.types.TimeMatesEntity -import io.timemates.sdk.common.exceptions.* /** * Represents a type-safe wrapper class for handling exceptions in the context of an operation's result. @@ -18,7 +22,7 @@ import io.timemates.sdk.common.exceptions.* * @param E The type of the exception. * @property result The original result of the operation. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) @JvmInline public value class SafeExceptionResult @InternalApi constructor( @property:InternalApi public val result: Result @@ -33,7 +37,7 @@ public value class SafeExceptionResult @InternalApi constructo * @receiver The original result of the operation. * @return The [SafeExceptionResult] containing the original result. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) public fun Result.safeResult(): SafeExceptionResult { return SafeExceptionResult(this) } @@ -138,7 +142,7 @@ public fun SafeExceptionResult.ignoreNotFound(): SafeE * @param block The block of code to be executed if any exception is encountered. * @return The [SafeExceptionResult] after executing the block. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) public inline fun SafeExceptionResult.whenOtherError( block: (E) -> Unit ): SafeExceptionResult { @@ -157,7 +161,7 @@ public inline fun SafeExceptionResult.whenOtherError( * * But, if it's possible, it's better to use just [Result] API instead of [SafeExceptionResult]. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) public inline fun SafeExceptionResult.whenAnyError( block: (Throwable) -> Unit ): SafeExceptionResult { diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/pagination/PagesIterator.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/pagination/PagesIterator.kt index fddd1d7..647c137 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/pagination/PagesIterator.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/pagination/PagesIterator.kt @@ -1,7 +1,7 @@ package io.timemates.sdk.common.pagination import io.timemates.sdk.common.annotations.ApiStatus -import io.timemates.sdk.common.annotations.ExperimentalApi +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi import io.timemates.sdk.common.constructor.createOrThrow import io.timemates.sdk.common.exceptions.TimeMatesException import io.timemates.sdk.common.pagination.PagesIteratorImpl.State @@ -60,7 +60,7 @@ public fun PagesIterator.asFlow(): Flow>> = flow { * * @return A [List] containing all elements from the page iterator. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) public suspend fun PagesIterator.toList(): List> { return buildList { for (result in this@toList) { @@ -78,7 +78,7 @@ public suspend fun PagesIterator.toList(): List> { * * @return A [Sequence] containing all elements from the page iterator. */ -@ExperimentalApi(status = ApiStatus.NEEDS_REVISION) +@ExperimentalTimeMatesApi(status = ApiStatus.NEEDS_REVISION) public suspend fun PagesIterator.asSequence(): Sequence> { return toList().asSequence() } @@ -99,7 +99,7 @@ public suspend inline fun PagesIterator.forEachPage(block: (Result PagesIterator.forEach(block: (Result) -> Unit) { forEachPage { page -> if (page.isSuccess) { diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/AuthorizedTimeMatesRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/AuthorizedTimeMatesRequest.kt new file mode 100644 index 0000000..36bffc7 --- /dev/null +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/AuthorizedTimeMatesRequest.kt @@ -0,0 +1,18 @@ +package io.timemates.sdk.common.types + +import io.timemates.sdk.authorization.types.value.AccessHash + +/** + * An abstract class representing an authorized request within the TimeMates system. + * Subclasses of this class are used to perform operations that require valid + * authorization via an access hash. + * + * @param R The response type expected from the request. + */ +public abstract class AuthorizedTimeMatesRequest : TimeMatesRequest() { + /** + * The access hash associated with this authorized request. + * It is used for authentication and authorization purposes. + */ + public abstract val accessHash: AccessHash +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/TimeMatesRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/TimeMatesRequest.kt index b74177f..531a182 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/TimeMatesRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/common/types/TimeMatesRequest.kt @@ -8,4 +8,15 @@ package io.timemates.sdk.common.types * * @param R The type of the response expected from the request. */ -public abstract class TimeMatesRequest internal constructor() : TimeMatesEntity() \ No newline at end of file +public abstract class TimeMatesRequest internal constructor() : TimeMatesEntity() { + /** + * A unique key that identifies this request type. + */ + public abstract val requestKey: Key<*> + + /** + * An interface representing the key associated with a [TimeMatesRequest]. + * @param T The specific type of the [TimeMatesRequest]. + */ + public interface Key> +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/GetFileBytesRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/GetFileBytesRequest.kt index 8aa4b3e..d5faea7 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/GetFileBytesRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/GetFileBytesRequest.kt @@ -8,7 +8,11 @@ import kotlinx.coroutines.flow.Flow public data class GetFileBytesRequest( val fileId: FileId, ) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + public data class Result( val bytes: Flow ) : TimeMatesEntity() + + override val requestKey: Key = Key } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/UploadFileRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/UploadFileRequest.kt index 00e1c44..2d2d9bb 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/UploadFileRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/requests/UploadFileRequest.kt @@ -1,18 +1,18 @@ package io.timemates.sdk.files.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesEntity -import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.files.types.FileType import io.timemates.sdk.files.types.value.FileId import io.timemates.sdk.files.types.value.FileName import kotlinx.coroutines.flow.Flow public data class UploadFileRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val bytes: Flow, val fileName: FileName, val fileType: FileType, -) : TimeMatesRequest() { +) : AuthorizedTimeMatesRequest() { public data class Result(val fileId: FileId) : TimeMatesEntity() } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/types/FileType.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/types/FileType.kt index 986a99d..8cd32c8 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/files/types/FileType.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/files/types/FileType.kt @@ -1,7 +1,5 @@ package io.timemates.sdk.files.types -import io.timemates.sdk.common.types.TimeMatesEntity - public enum class FileType { IMAGE, } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/CreateInviteRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/CreateInviteRequest.kt index fbe8f2b..c4279f6 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/CreateInviteRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/CreateInviteRequest.kt @@ -1,17 +1,21 @@ package io.timemates.sdk.timers.members.invites.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.common.types.value.Count import io.timemates.sdk.timers.members.invites.types.value.InviteCode -import io.timemates.sdk.timers.members.invites.types.value.InviteName import io.timemates.sdk.timers.types.value.TimerId public data class CreateInviteRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, val maxJoinersCount: Count, -) : TimeMatesRequest() { +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key + public data class Result(public val inviteCode: InviteCode) : TimeMatesEntity() } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/GetInvitesRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/GetInvitesRequest.kt index 3a22851..bdef1d1 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/GetInvitesRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/GetInvitesRequest.kt @@ -3,13 +3,17 @@ package io.timemates.sdk.timers.members.invites.requests import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.pagination.Page import io.timemates.sdk.common.pagination.PageToken -import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.members.invites.types.Invite import io.timemates.sdk.timers.types.value.TimerId public data class GetInvitesRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, val pageToken: PageToken?, -) : TimeMatesRequest>() \ No newline at end of file +) : AuthorizedTimeMatesRequest>() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/JoinTimerByCodeRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/JoinTimerByCodeRequest.kt new file mode 100644 index 0000000..b698124 --- /dev/null +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/JoinTimerByCodeRequest.kt @@ -0,0 +1,18 @@ +package io.timemates.sdk.timers.members.invites.requests + +import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.TimeMatesRequest +import io.timemates.sdk.timers.members.invites.types.value.InviteCode +import io.timemates.sdk.timers.types.value.TimerId + +public data class JoinTimerByCodeRequest( + public val code: InviteCode, + public val accessHash: AccessHash, +) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key + + public data class Result(val timerId: TimerId) : TimeMatesEntity() +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/RemoveInviteRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/RemoveInviteRequest.kt index f26c260..df6152a 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/RemoveInviteRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/invites/requests/RemoveInviteRequest.kt @@ -1,13 +1,18 @@ package io.timemates.sdk.timers.members.invites.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.members.invites.types.value.InviteCode import io.timemates.sdk.timers.types.value.TimerId public data class RemoveInviteRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, val inviteCode: InviteCode, -) : TimeMatesRequest() \ No newline at end of file +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/GetMembersRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/GetMembersRequest.kt index c8e4d1b..bdaac90 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/GetMembersRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/GetMembersRequest.kt @@ -3,13 +3,17 @@ package io.timemates.sdk.timers.members.requests import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.pagination.Page import io.timemates.sdk.common.pagination.PageToken -import io.timemates.sdk.common.types.TimeMatesEntity +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.value.TimerId import io.timemates.sdk.users.profile.types.User public data class GetMembersRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, val pageToken: PageToken?, -) : TimeMatesRequest>() \ No newline at end of file +) : AuthorizedTimeMatesRequest>() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/KickMemberRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/KickMemberRequest.kt index 8b8909a..a3005f8 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/KickMemberRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/members/requests/KickMemberRequest.kt @@ -10,4 +10,8 @@ public data class KickMemberRequest( val accessHash: AccessHash, val timerId: TimerId, val userId: UserId, -) : TimeMatesRequest() \ No newline at end of file +) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/CreateTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/CreateTimerRequest.kt index 759de46..be3e950 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/CreateTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/CreateTimerRequest.kt @@ -1,6 +1,7 @@ package io.timemates.sdk.timers.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.TimerSettings @@ -9,10 +10,14 @@ import io.timemates.sdk.timers.types.value.TimerId import io.timemates.sdk.timers.types.value.TimerName public data class CreateTimerRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val name: TimerName, val description: TimerDescription, val settings: TimerSettings, -) : TimeMatesRequest() { +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key + public data class Result(val timerId: TimerId) : TimeMatesEntity() } diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/EditTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/EditTimerRequest.kt index b194b7b..4a72708 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/EditTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/EditTimerRequest.kt @@ -1,6 +1,7 @@ package io.timemates.sdk.timers.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.TimerSettings @@ -9,9 +10,13 @@ import io.timemates.sdk.timers.types.value.TimerId import io.timemates.sdk.timers.types.value.TimerName public data class EditTimerRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, val name: TimerName? = null, val description: TimerDescription? = null, val settings: TimerSettings.Patch? = null, -) : TimeMatesRequest() \ No newline at end of file +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetTimerRequest.kt index 2b6f6b8..d84b5c3 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetTimerRequest.kt @@ -1,15 +1,20 @@ package io.timemates.sdk.timers.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.Timer import io.timemates.sdk.timers.types.value.TimerId public data class GetTimerRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() { +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key + public data class Result( val timer: Timer, ) : TimeMatesEntity() diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetUserTimersRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetUserTimersRequest.kt index f5f86e2..68a9f61 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetUserTimersRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/GetUserTimersRequest.kt @@ -3,10 +3,15 @@ package io.timemates.sdk.timers.requests import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.pagination.Page import io.timemates.sdk.common.pagination.PageToken +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.Timer public data class GetUserTimersRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val pageToken: PageToken?, -) : TimeMatesRequest>() \ No newline at end of file +) : AuthorizedTimeMatesRequest>() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/RemoveTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/RemoveTimerRequest.kt index 262a9e6..60f4b72 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/RemoveTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/requests/RemoveTimerRequest.kt @@ -8,4 +8,8 @@ import io.timemates.sdk.timers.types.value.TimerId public data class RemoveTimerRequest( val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() \ No newline at end of file +) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/ConfirmTimerRoundRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/ConfirmTimerRoundRequest.kt index 07e7533..07d97ad 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/ConfirmTimerRoundRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/ConfirmTimerRoundRequest.kt @@ -1,10 +1,14 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest -import io.timemates.sdk.timers.types.value.TimerId public data class ConfirmTimerRoundRequest( - val accessHash: AccessHash, -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetTimerStateRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetTimerStateRequest.kt index 8f5fc45..096e887 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetTimerStateRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetTimerStateRequest.kt @@ -1,7 +1,7 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash -import io.timemates.sdk.common.types.Empty +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesEntity import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.Timer @@ -12,8 +12,12 @@ import kotlinx.coroutines.flow.Flow * Gets timer session state. */ public data class GetTimerStateRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() { +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key + public data class Result(val flow: Flow) : TimeMatesEntity() } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetUserCurrentSessionRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetUserCurrentSessionRequest.kt index b87f957..bbab4bf 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetUserCurrentSessionRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/GetUserCurrentSessionRequest.kt @@ -1,6 +1,7 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.Timer @@ -8,5 +9,10 @@ import io.timemates.sdk.timers.types.Timer * Gets current timer session. */ public data class GetUserCurrentSessionRequest( - val accessHash: AccessHash, -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/JoinTimerSessionRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/JoinTimerSessionRequest.kt index 0727f89..c60c0de 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/JoinTimerSessionRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/JoinTimerSessionRequest.kt @@ -1,11 +1,16 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.value.TimerId public data class JoinTimerSessionRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() \ No newline at end of file +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/LeaveTimerSessionRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/LeaveTimerSessionRequest.kt index b93e0cb..ff23c1b 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/LeaveTimerSessionRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/LeaveTimerSessionRequest.kt @@ -1,10 +1,14 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest -import io.timemates.sdk.timers.types.value.TimerId public data class LeaveTimerSessionRequest( - val accessHash: AccessHash, -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/PingSessionRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/PingSessionRequest.kt index bbb741b..8c48343 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/PingSessionRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/PingSessionRequest.kt @@ -1,10 +1,14 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest -import io.timemates.sdk.timers.types.value.TimerId public data class PingSessionRequest( - val accessHash: AccessHash, -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StartTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StartTimerRequest.kt index 3591187..d79d4f5 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StartTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StartTimerRequest.kt @@ -1,6 +1,7 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.value.TimerId @@ -9,6 +10,10 @@ import io.timemates.sdk.timers.types.value.TimerId * Starts timer session if user didn't joined any yet. */ public data class StartTimerRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() \ No newline at end of file +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StopTimerRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StopTimerRequest.kt index d8849d0..77af17c 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StopTimerRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/timers/sessions/requests/StopTimerRequest.kt @@ -1,6 +1,7 @@ package io.timemates.sdk.timers.sessions.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.timers.types.value.TimerId @@ -9,6 +10,10 @@ import io.timemates.sdk.timers.types.value.TimerId * Stops timer session. */ public data class StopTimerRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val timerId: TimerId, -) : TimeMatesRequest() \ No newline at end of file +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/UserApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/UserApi.kt index 50e6cf5..3ed3b49 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/UserApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/UserApi.kt @@ -1,6 +1,5 @@ package io.timemates.sdk.users -import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.engine.TimeMatesRequestsEngine import io.timemates.sdk.common.providers.AccessHashProvider import io.timemates.sdk.users.profile.ProfileApi @@ -10,7 +9,7 @@ import io.timemates.sdk.users.settings.UserSettingsApi * Provides access to user-related functionality through the API. * * @param engine The TimeMatesRequestsEngine instance used for making API requests. - * @param accessHash The access hash for authentication purposes. + * @param tokenProvider The provider of access hash for authentication purposes. */ public class UserApi(engine: TimeMatesRequestsEngine, tokenProvider: AccessHashProvider) { /** diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/ProfileApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/ProfileApi.kt index eda56f8..769edf7 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/ProfileApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/ProfileApi.kt @@ -9,7 +9,6 @@ import io.timemates.sdk.users.profile.requests.EditProfileRequest import io.timemates.sdk.users.profile.requests.GetUsersRequest import io.timemates.sdk.users.profile.types.Avatar import io.timemates.sdk.users.profile.types.User -import io.timemates.sdk.users.profile.types.value.EmailAddress import io.timemates.sdk.users.profile.types.value.UserDescription import io.timemates.sdk.users.profile.types.value.UserId import io.timemates.sdk.users.profile.types.value.UserName @@ -18,7 +17,7 @@ import io.timemates.sdk.users.profile.types.value.UserName * Provides functionality for accessing and modifying user profiles through the API. * * @property engine The TimeMatesRequestsEngine instance used for making API requests. - * @property accessHash The access hash for authentication purposes. + * @property tokenProvider The provider of access hash for authentication purposes. */ public class ProfileApi( private val engine: TimeMatesRequestsEngine, diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/EditProfileRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/EditProfileRequest.kt index cbe97af..3bfe96b 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/EditProfileRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/EditProfileRequest.kt @@ -1,16 +1,20 @@ package io.timemates.sdk.users.profile.requests import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest -import io.timemates.sdk.files.types.value.FileId import io.timemates.sdk.users.profile.types.Avatar import io.timemates.sdk.users.profile.types.value.UserDescription import io.timemates.sdk.users.profile.types.value.UserName public data class EditProfileRequest( - val accessHash: AccessHash, + override val accessHash: AccessHash, val name: UserName?, val description: UserDescription?, - val avatar: Avatar? -) : TimeMatesRequest() \ No newline at end of file + val avatar: Avatar?, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/GetUsersRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/GetUsersRequest.kt index 353e241..9c8af86 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/GetUsersRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/requests/GetUsersRequest.kt @@ -8,5 +8,9 @@ import io.timemates.sdk.users.profile.types.value.UserId public data class GetUsersRequest( val users: List, ) : TimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + public data class Result(val users: List) : TimeMatesEntity() + + override val requestKey: Key get() = Key } \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/types/User.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/types/User.kt index 9f4b62f..70bbc93 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/types/User.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/profile/types/User.kt @@ -12,13 +12,13 @@ import io.timemates.sdk.users.profile.types.value.UserName * @property id The unique identifier of the user. * @property name The name of the user. * @property description The description of the user. - * @property avatarFileId The unique identifier of the user's avatar file. + * @property avatar The user's avatar file. * @property emailAddress The email address associated with the user (null if not available). */ public data class User( val id: UserId, val name: UserName, - val description: UserDescription, + val description: UserDescription?, val emailAddress: EmailAddress?, val avatar: Avatar?, ) : TimeMatesEntity() \ No newline at end of file diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/UserSettingsApi.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/UserSettingsApi.kt index bb09758..5833f98 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/UserSettingsApi.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/UserSettingsApi.kt @@ -1,6 +1,5 @@ package io.timemates.sdk.users.settings -import io.timemates.sdk.authorization.types.value.AccessHash import io.timemates.sdk.common.annotations.UnimplementedApi import io.timemates.sdk.common.engine.TimeMatesRequestsEngine import io.timemates.sdk.common.providers.AccessHashProvider diff --git a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/requests/EditEmailRequest.kt b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/requests/EditEmailRequest.kt index b697a52..c487b9b 100644 --- a/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/requests/EditEmailRequest.kt +++ b/sdk/src/commonMain/kotlin/io/timemates/sdk/users/settings/requests/EditEmailRequest.kt @@ -1,9 +1,25 @@ package io.timemates.sdk.users.settings.requests +import io.timemates.sdk.authorization.types.value.AccessHash +import io.timemates.sdk.common.annotations.ApiStatus +import io.timemates.sdk.common.annotations.ExperimentalTimeMatesApi +import io.timemates.sdk.common.types.AuthorizedTimeMatesRequest import io.timemates.sdk.common.types.Empty import io.timemates.sdk.common.types.TimeMatesRequest import io.timemates.sdk.users.profile.types.value.EmailAddress +/** + * This request is not implemented on server yet. Always throws + * [io.timemates.sdk.common.exceptions.UnsupportedException]. + * + * TODO: remove notice once implemented + */ +@ExperimentalTimeMatesApi(status = ApiStatus.IN_PROGRESS) public data class EditEmailRequest( val newEmail: EmailAddress, -) : TimeMatesRequest() \ No newline at end of file + override val accessHash: AccessHash, +) : AuthorizedTimeMatesRequest() { + public companion object Key : TimeMatesRequest.Key + + override val requestKey: Key get() = Key +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index bd3faff..52e3530 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,4 +24,5 @@ includeBuild("build-logic/publish-library-plugin") include(":sdk") include(":grpc-engine") +include(":rsocket-engine") include(":grpc-engine:android")