Skip to content

Commit

Permalink
Add Apollo adapter for kotlinx.datetime.Instant.
Browse files Browse the repository at this point in the history
  • Loading branch information
ychescale9 committed Nov 24, 2023
1 parent 53799d7 commit 7352541
Show file tree
Hide file tree
Showing 23 changed files with 126 additions and 97 deletions.
2 changes: 1 addition & 1 deletion android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ androidComponents {

dependencies {
mockImplementation(project(":kmp:feed-datasource:testing"))
devImplementation(project(":kmp:feed-datasource:cloud"))
demoImplementation(project(":kmp:feed-datasource:edge"))
devImplementation(project(":kmp:feed-datasource:cloud"))
prodImplementation(project(":kmp:feed-datasource:cloud"))
implementation(project(":kmp:persistence"))
implementation(project(":kmp:data"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ internal fun Project.configureKotlinCommonCompileOptions() {
* Enable explicit API mode for non-test Kotlin compilations
*/
internal fun Project.enableExplicitApi() {
tasks.withType<KotlinCompile>().configureEach {
tasks.withType<KotlinCommonCompile>().configureEach {
if (!name.contains("TestKotlin")) {
kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
}
Expand Down
26 changes: 14 additions & 12 deletions detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@ complexity:
TooManyFunctions:
thresholdInFiles: 20

naming:
TopLevelPropertyNaming:
formatting:
Filename:
active: false
MaximumLineLength:
active: false

naming:
FunctionNaming:
ignoreAnnotated:
- Composable
TopLevelPropertyNaming:
constantPattern: '[A-Z][A-Za-z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'

style:
MagicNumber:
ignorePropertyDeclaration: true
UnnecessaryAbstractClass:
active: false
MaxLineLength:
excludes: ['**/test/**', '**/*Test/**']

formatting:
Filename:
active: false
ImportOrdering:
active: false
MaximumLineLength:
excludes: ['**/test/**', '**/*Test/**']
UnusedPrivateMember:
ignoreAnnotated:
- Preview
- ThemePreviews
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ androidx-espresso-contrib = { module = "androidx.test.espresso:espresso-contrib"
androidx-espresso-intents = { module = "androidx.test.espresso:espresso-intents", version.ref = "androidx-test-espresso" }
coil = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
apollo-runtime = { module = "com.apollographql.apollo3:apollo-runtime", version.ref = "apollo" }
apollo-api = { module = "com.apollographql.apollo3:apollo-api", version.ref = "apollo" }
apollo-normalizedCache = { module = "com.apollographql.apollo3:apollo-normalized-cache", version.ref = "apollo" }
apollo-adapters = { module = "com.apollographql.apollo3:apollo-adapters", version.ref = "apollo" }
apollo-testingSupport = { module = "com.apollographql.apollo3:apollo-testing-support", version.ref = "apollo" }
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
radiography = { module = "com.squareup.radiography:radiography", version.ref = "radiography" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.github.reactivecircus.kstreamlined.kmp.data.feed

import co.touchlab.kermit.Logger
import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedItem
import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedOriginItem
import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedOrigin
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.FeedDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
Expand All @@ -22,12 +22,12 @@ public class FeedRepository(
}
}

public suspend fun selectFeedSource(feedOrigin: FeedOriginItem) {
public suspend fun selectFeedSource(feedOrigin: FeedOrigin) {
feedOrigin.selected
TODO()
}

public suspend fun unselectFeedSource(feedOrigin: FeedOriginItem) {
public suspend fun unselectFeedSource(feedOrigin: FeedOrigin) {
feedOrigin.selected
TODO()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.github.reactivecircus.kstreamlined.kmp.data.feed

import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedItem
import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedOriginItem
import io.github.reactivecircus.kstreamlined.kmp.data.feed.model.FeedOrigin

public data class FeedSyncState(
val feedOrigins: List<FeedOriginItem>,
val feedOrigins: List<FeedOrigin>,
val feedItems: List<FeedItem>,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.github.reactivecircus.kstreamlined.kmp.data.feed.model

public data class FeedOriginItem(
public data class FeedOrigin(
val key: Key,
val title: String,
val description: String,
Expand Down
7 changes: 7 additions & 0 deletions kmp/feed-datasource/cloud/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ apollo {
introspection {
endpointUrl.set(envOrProp("KSTREAMLINED_API_ENDPOINT"))
}
mapScalar(
graphQLName = "Instant",
targetName = "kotlinx.datetime.Instant",
expression = "com.apollographql.apollo3.adapter.KotlinxInstantAdapter",
)
}
}

Expand All @@ -26,7 +31,9 @@ kotlin {
api(project(":kmp:feed-datasource:common"))
api(libs.apollo.runtime)
api(libs.apollo.normalizedCache)
implementation(libs.apollo.adapters)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.datetime)
implementation(libs.kermit)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ interface FeedEntry {
"""
Publish time of the feed entry in ISO 8601.
"""
publishTime: String!
publishTime: Instant!

"""
Url of the content.
Expand Down Expand Up @@ -316,6 +316,11 @@ enum FeedSourceKey {
KOTLIN_WEEKLY
}

"""
ISO 8601 instant.
"""
scalar Instant

type KotlinBlog implements FeedEntry {
"""
Unique id of the feed entry.
Expand All @@ -330,7 +335,7 @@ type KotlinBlog implements FeedEntry {
"""
Publish time of the feed entry in ISO 8601.
"""
publishTime: String!
publishTime: Instant!

"""
Url of the content.
Expand Down Expand Up @@ -362,7 +367,7 @@ type KotlinWeekly implements FeedEntry {
"""
Publish time of the feed entry in ISO 8601.
"""
publishTime: String!
publishTime: Instant!

"""
Url of the content.
Expand All @@ -384,7 +389,7 @@ type KotlinYouTube implements FeedEntry {
"""
Publish time of the feed entry in ISO 8601.
"""
publishTime: String!
publishTime: Instant!

"""
Url of the content.
Expand Down Expand Up @@ -430,7 +435,7 @@ type TalkingKotlin implements FeedEntry {
"""
Publish time of the feed entry in ISO 8601.
"""
publishTime: String!
publishTime: Instant!

"""
Url of the content.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import io.github.reactivecircus.kstreamlined.graphql.FeedSourcesQuery
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.mapper.asApolloModel
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.mapper.asExternalModel
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedEntry
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedOrigin
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedSource
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.networking.defaultFetchPolicy

public class CloudFeedDataSource(private val apolloClient: ApolloClient) : FeedDataSource {

override suspend fun loadFeedOrigins(refresh: Boolean): List<FeedOrigin> {
override suspend fun loadFeedOrigins(refresh: Boolean): List<FeedSource> {
return runCatching {
apolloClient.query(FeedSourcesQuery())
.defaultFetchPolicy(refresh)
Expand All @@ -25,7 +25,7 @@ public class CloudFeedDataSource(private val apolloClient: ApolloClient) : FeedD
}

override suspend fun loadFeedEntries(
filters: List<FeedOrigin.Key>?,
filters: List<FeedSource.Key>?,
refresh: Boolean,
): List<FeedEntry> {
return runCatching {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@ package io.github.reactivecircus.kstreamlined.kmp.feed.datasource.mapper

import io.github.reactivecircus.kstreamlined.graphql.FeedSourcesQuery
import io.github.reactivecircus.kstreamlined.graphql.type.FeedSourceKey
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedOrigin
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedSource

internal fun FeedOrigin.Key.asApolloModel(): FeedSourceKey {
internal fun FeedSource.Key.asApolloModel(): FeedSourceKey {
return when (this) {
FeedOrigin.Key.KotlinBlog -> FeedSourceKey.KOTLIN_BLOG
FeedOrigin.Key.KotlinYouTubeChannel -> FeedSourceKey.KOTLIN_YOUTUBE_CHANNEL
FeedOrigin.Key.TalkingKotlinPodcast -> FeedSourceKey.TALKING_KOTLIN_PODCAST
FeedOrigin.Key.KotlinWeekly -> FeedSourceKey.KOTLIN_WEEKLY
FeedSource.Key.KotlinBlog -> FeedSourceKey.KOTLIN_BLOG
FeedSource.Key.KotlinYouTubeChannel -> FeedSourceKey.KOTLIN_YOUTUBE_CHANNEL
FeedSource.Key.TalkingKotlinPodcast -> FeedSourceKey.TALKING_KOTLIN_PODCAST
FeedSource.Key.KotlinWeekly -> FeedSourceKey.KOTLIN_WEEKLY
}
}

internal fun FeedSourcesQuery.FeedSource.asExternalModel(): FeedOrigin? {
return FeedOrigin(
internal fun FeedSourcesQuery.FeedSource.asExternalModel(): FeedSource? {
return FeedSource(
key = when (this.key) {
FeedSourceKey.KOTLIN_BLOG -> FeedOrigin.Key.KotlinBlog
FeedSourceKey.KOTLIN_YOUTUBE_CHANNEL -> FeedOrigin.Key.KotlinYouTubeChannel
FeedSourceKey.TALKING_KOTLIN_PODCAST -> FeedOrigin.Key.TalkingKotlinPodcast
FeedSourceKey.KOTLIN_WEEKLY -> FeedOrigin.Key.KotlinWeekly
FeedSourceKey.KOTLIN_BLOG -> FeedSource.Key.KotlinBlog
FeedSourceKey.KOTLIN_YOUTUBE_CHANNEL -> FeedSource.Key.KotlinYouTubeChannel
FeedSourceKey.TALKING_KOTLIN_PODCAST -> FeedSource.Key.TalkingKotlinPodcast
FeedSourceKey.KOTLIN_WEEKLY -> FeedSource.Key.KotlinWeekly
FeedSourceKey.UNKNOWN__ -> return null
},
title = this.title,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.reactivecircus.kstreamlined.kmp.feed.datasource

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.annotations.ApolloExperimental
import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory
import com.apollographql.apollo3.cache.normalized.normalizedCache
import com.apollographql.apollo3.exception.ApolloHttpException
Expand All @@ -17,12 +16,12 @@ import io.github.reactivecircus.kstreamlined.graphql.type.buildKotlinBlog
import io.github.reactivecircus.kstreamlined.graphql.type.buildKotlinYouTube
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.mapper.asExternalModel
import io.github.reactivecircus.kstreamlined.kmp.test.utils.runTest
import kotlinx.datetime.toInstant
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue

@ApolloExperimental
class CloudFeedDataSourceTest {

private lateinit var mockServer: MockServer
Expand All @@ -44,9 +43,11 @@ class CloudFeedDataSourceTest {
feedEntries = listOf(
buildKotlinBlog {
title = "Kotlin blog entry"
publishTime = "2023-11-16T11:59:46Z".toInstant()
},
buildKotlinYouTube {
title = "Kotlin YouTube entry"
publishTime = "2023-11-21T18:47:47Z".toInstant()
}
)
}.feedEntries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.github.reactivecircus.kstreamlined.graphql.type.buildKotlinWeekly
import io.github.reactivecircus.kstreamlined.graphql.type.buildKotlinYouTube
import io.github.reactivecircus.kstreamlined.graphql.type.buildTalkingKotlin
import io.github.reactivecircus.kstreamlined.kmp.feed.datasource.model.FeedEntry
import kotlinx.datetime.toInstant
import kotlin.test.Test
import kotlin.test.assertEquals

Expand All @@ -18,7 +19,7 @@ class FeedEntryMappersTest {
buildKotlinBlog {
id = "1"
title = "Kotlin Blog Post"
publishTime = "2022-01-01T00:00:00Z"
publishTime = "2022-01-01T00:00:00Z".toInstant()
contentUrl = "https://blog.kotlinlang.org/post"
featuredImageUrl = "https://blog.kotlinlang.org/image"
description = "A blog post about Kotlin"
Expand All @@ -29,7 +30,7 @@ class FeedEntryMappersTest {
val expectedFeedEntry = FeedEntry.KotlinBlog(
id = "1",
title = "Kotlin Blog Post",
publishTime = "2022-01-01T00:00:00Z",
publishTime = "2022-01-01T00:00:00Z".toInstant(),
contentUrl = "https://blog.kotlinlang.org/post",
featuredImageUrl = "https://blog.kotlinlang.org/image",
description = "A blog post about Kotlin",
Expand All @@ -45,7 +46,7 @@ class FeedEntryMappersTest {
buildKotlinYouTube {
id = "2"
title = "Kotlin YouTube Video"
publishTime = "2022-01-02T00:00:00Z"
publishTime = "2022-01-02T00:00:00Z".toInstant()
contentUrl = "https://youtube.com/kotlinvideo"
thumbnailUrl = "https://youtube.com/kotlinvideo/thumbnail"
description = "A YouTube video about Kotlin"
Expand All @@ -56,7 +57,7 @@ class FeedEntryMappersTest {
val expectedFeedEntry = FeedEntry.KotlinYouTube(
id = "2",
title = "Kotlin YouTube Video",
publishTime = "2022-01-02T00:00:00Z",
publishTime = "2022-01-02T00:00:00Z".toInstant(),
contentUrl = "https://youtube.com/kotlinvideo",
thumbnailUrl = "https://youtube.com/kotlinvideo/thumbnail",
description = "A YouTube video about Kotlin",
Expand All @@ -72,7 +73,7 @@ class FeedEntryMappersTest {
buildTalkingKotlin {
id = "3"
title = "Talking Kotlin Podcast"
publishTime = "2022-01-03T00:00:00Z"
publishTime = "2022-01-03T00:00:00Z".toInstant()
contentUrl = "https://talkingkotlin.com/podcast"
podcastLogoUrl = "https://talkingkotlin.com/podcast/logo"
tags = listOf("Kotlin", "Podcast")
Expand All @@ -83,7 +84,7 @@ class FeedEntryMappersTest {
val expectedFeedEntry = FeedEntry.TalkingKotlin(
id = "3",
title = "Talking Kotlin Podcast",
publishTime = "2022-01-03T00:00:00Z",
publishTime = "2022-01-03T00:00:00Z".toInstant(),
contentUrl = "https://talkingkotlin.com/podcast",
podcastLogoUrl = "https://talkingkotlin.com/podcast/logo",
tags = listOf("Kotlin", "Podcast"),
Expand All @@ -99,7 +100,7 @@ class FeedEntryMappersTest {
buildKotlinWeekly {
id = "4"
title = "Kotlin Weekly Newsletter"
publishTime = "2022-01-04T00:00:00Z"
publishTime = "2022-01-04T00:00:00Z".toInstant()
contentUrl = "https://kotlinweekly.net/newsletter"
},
)
Expand All @@ -108,7 +109,7 @@ class FeedEntryMappersTest {
val expectedFeedEntry = FeedEntry.KotlinWeekly(
id = "4",
title = "Kotlin Weekly Newsletter",
publishTime = "2022-01-04T00:00:00Z",
publishTime = "2022-01-04T00:00:00Z".toInstant(),
contentUrl = "https://kotlinweekly.net/newsletter",
)

Expand Down
Loading

0 comments on commit 7352541

Please sign in to comment.