mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 19:57:04 +05:30
refactor(database): split out JVM and Android parts
This commit is contained in:
parent
1b1984064c
commit
7b0b206905
31 changed files with 33 additions and 19 deletions
1
database/impl/.gitignore
vendored
Normal file
1
database/impl/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
32
database/impl/build.gradle.kts
Normal file
32
database/impl/build.gradle.kts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright © 2021-2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
import dev.msfjarvis.claw.gradle.addTestDependencies
|
||||
|
||||
plugins {
|
||||
id("dev.msfjarvis.claw.android-library")
|
||||
id("dev.msfjarvis.claw.kotlin-android")
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
alias(libs.plugins.anvil)
|
||||
alias(libs.plugins.whetstone)
|
||||
}
|
||||
|
||||
android { namespace = "dev.msfjarvis.claw.database" }
|
||||
|
||||
anvil { generateDaggerFactories.set(true) }
|
||||
|
||||
dependencies {
|
||||
api(projects.database.core)
|
||||
implementation(libs.dagger)
|
||||
implementation(libs.sqldelight.androidDriver)
|
||||
implementation(libs.sqldelight.primitiveAdapters)
|
||||
implementation(libs.sqlite.android)
|
||||
implementation(libs.kotlinx.serialization.core)
|
||||
|
||||
testImplementation(libs.sqldelight.jvmDriver)
|
||||
testImplementation(libs.kotlinx.serialization.json)
|
||||
addTestDependencies(project)
|
||||
}
|
1
database/impl/consumer-rules.pro
Normal file
1
database/impl/consumer-rules.pro
Normal file
|
@ -0,0 +1 @@
|
|||
-keep class dev.msfjarvis.claw.database.model.** { *; }
|
4
database/impl/lint-baseline.xml
Normal file
4
database/impl/lint-baseline.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<issues format="6" by="lint 8.3.0-alpha02" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha02)" variant="all" version="8.3.0-alpha02">
|
||||
|
||||
</issues>
|
7
database/impl/src/main/AndroidManifest.xml
Normal file
7
database/impl/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<!--
|
||||
~ Copyright © 2021-2023 Harsh Shandilya.
|
||||
~ Use of this source code is governed by an MIT-style
|
||||
~ license that can be found in the LICENSE file or at
|
||||
~ https://opensource.org/licenses/MIT.
|
||||
-->
|
||||
<manifest />
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database
|
||||
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.element
|
||||
import kotlinx.serialization.encoding.CompositeDecoder
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.encoding.decodeStructure
|
||||
import kotlinx.serialization.encoding.encodeStructure
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
object SavedPostSerializer : KSerializer<SavedPost> {
|
||||
private val delegateSerializer = ListSerializer(String.serializer())
|
||||
override val descriptor: SerialDescriptor =
|
||||
buildClassSerialDescriptor("SavedPost") {
|
||||
element<String>("shortId")
|
||||
element<String>("title")
|
||||
element<String>("url")
|
||||
element<String>("createdAt")
|
||||
element<Int?>("commentCount", isOptional = true)
|
||||
element<String>("commentsUrl")
|
||||
element<String>("submitterName")
|
||||
element<String>("submitterAvatarUrl")
|
||||
element<List<String>>("tags")
|
||||
element<String>("description")
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): SavedPost {
|
||||
return decoder.decodeStructure(descriptor) {
|
||||
var shortId = ""
|
||||
var title = ""
|
||||
var url = ""
|
||||
var createdAt = ""
|
||||
var commentCount: Int? = null
|
||||
var commentsUrl = ""
|
||||
var submitterName = ""
|
||||
var submitterAvatarUrl = ""
|
||||
var tags = emptyList<String>()
|
||||
var description = ""
|
||||
while (true) {
|
||||
when (val index = decodeElementIndex(descriptor)) {
|
||||
0 -> shortId = decodeStringElement(descriptor, 0)
|
||||
1 -> title = decodeStringElement(descriptor, 1)
|
||||
2 -> url = decodeStringElement(descriptor, 2)
|
||||
3 -> createdAt = decodeStringElement(descriptor, 3)
|
||||
4 -> commentCount = decodeNullableSerializableElement(descriptor, 4, Int.serializer())
|
||||
5 -> commentsUrl = decodeStringElement(descriptor, 5)
|
||||
6 -> submitterName = decodeStringElement(descriptor, 6)
|
||||
7 -> submitterAvatarUrl = decodeStringElement(descriptor, 7)
|
||||
8 -> tags = decodeSerializableElement(descriptor, 8, delegateSerializer)
|
||||
9 -> description = decodeStringElement(descriptor, 9)
|
||||
CompositeDecoder.DECODE_DONE -> break
|
||||
else -> error("Unexpected index: $index")
|
||||
}
|
||||
}
|
||||
SavedPost(
|
||||
shortId = shortId,
|
||||
title = title,
|
||||
url = url,
|
||||
createdAt = createdAt,
|
||||
commentCount = commentCount,
|
||||
commentsUrl = commentsUrl,
|
||||
submitterName = submitterName,
|
||||
submitterAvatarUrl = submitterAvatarUrl,
|
||||
tags = tags,
|
||||
description = description,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SavedPost) {
|
||||
encoder.encodeStructure(descriptor) {
|
||||
encodeStringElement(descriptor, 0, value.shortId)
|
||||
encodeStringElement(descriptor, 1, value.title)
|
||||
encodeStringElement(descriptor, 2, value.url)
|
||||
encodeStringElement(descriptor, 3, value.createdAt)
|
||||
encodeNullableSerializableElement(descriptor, 4, Int.serializer(), value.commentCount)
|
||||
encodeStringElement(descriptor, 5, value.commentsUrl)
|
||||
encodeStringElement(descriptor, 6, value.submitterName)
|
||||
encodeStringElement(descriptor, 7, value.submitterAvatarUrl)
|
||||
encodeSerializableElement(descriptor, 8, delegateSerializer, value.tags)
|
||||
encodeStringElement(descriptor, 9, value.description)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright © 2021-2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.injection
|
||||
|
||||
import android.content.Context
|
||||
import app.cash.sqldelight.adapter.primitive.IntColumnAdapter
|
||||
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
|
||||
import com.deliveryhero.whetstone.app.ApplicationScope
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import com.squareup.anvil.annotations.optional.ForScope
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dev.msfjarvis.claw.database.LobstersDatabase
|
||||
import dev.msfjarvis.claw.database.local.PostComments
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import dev.msfjarvis.claw.database.model.CSVAdapter
|
||||
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
|
||||
|
||||
@Module
|
||||
@ContributesTo(ApplicationScope::class)
|
||||
object DatabaseModule {
|
||||
|
||||
private const val LOBSTERS_DATABASE_NAME = "SavedPosts.db"
|
||||
|
||||
@[Provides InternalDatabaseApi]
|
||||
fun provideDatabase(@ForScope(ApplicationScope::class) context: Context): LobstersDatabase {
|
||||
val driver =
|
||||
AndroidSqliteDriver(
|
||||
schema = LobstersDatabase.Schema,
|
||||
context = context,
|
||||
name = LOBSTERS_DATABASE_NAME,
|
||||
factory = RequerySQLiteOpenHelperFactory(),
|
||||
)
|
||||
return LobstersDatabase(
|
||||
driver = driver,
|
||||
PostCommentsAdapter = PostComments.Adapter(CSVAdapter()),
|
||||
SavedPostAdapter = SavedPost.Adapter(IntColumnAdapter, CSVAdapter()),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.injection
|
||||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
/**
|
||||
* Neato workaround for not allowing the [dev.msfjarvis.claw.database.LobstersDatabase] type to be
|
||||
* used directly by modules that depend on this one, as we prefer them to use the specific types
|
||||
* from [QueriesModule] instead. A [Qualifier] applied to the
|
||||
* [dev.msfjarvis.claw.database.LobstersDatabase] type makes all injection sites require it as well,
|
||||
* and marking the annotation class' visibility as `internal` lets it stay visible to the Java code
|
||||
* generated by Dagger but inaccessible by the Kotlin code we're writing ourselves.
|
||||
*/
|
||||
@Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class InternalDatabaseApi
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.injection
|
||||
|
||||
import com.deliveryhero.whetstone.app.ApplicationScope
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dev.msfjarvis.claw.database.LobstersDatabase
|
||||
import dev.msfjarvis.claw.database.local.PostCommentsQueries
|
||||
import dev.msfjarvis.claw.database.local.ReadPostsQueries
|
||||
import dev.msfjarvis.claw.database.local.SavedPostQueries
|
||||
|
||||
@Module
|
||||
@ContributesTo(ApplicationScope::class)
|
||||
object QueriesModule {
|
||||
|
||||
@Provides
|
||||
fun provideSavedPostsQueries(@InternalDatabaseApi database: LobstersDatabase): SavedPostQueries {
|
||||
return database.savedPostQueries
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun providePostCommentsQueries(
|
||||
@InternalDatabaseApi database: LobstersDatabase
|
||||
): PostCommentsQueries {
|
||||
return database.postCommentsQueries
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideReadPostsQueries(
|
||||
@InternalDatabaseApi database: LobstersDatabase,
|
||||
): ReadPostsQueries {
|
||||
return database.readPostsQueries
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright © 2021-2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.model
|
||||
|
||||
import app.cash.sqldelight.ColumnAdapter
|
||||
|
||||
class CSVAdapter : ColumnAdapter<List<String>, String> {
|
||||
override fun decode(databaseValue: String): List<String> {
|
||||
return databaseValue.split(SEPARATOR)
|
||||
}
|
||||
|
||||
override fun encode(value: List<String>): String {
|
||||
return value.joinToString(SEPARATOR)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val SEPARATOR = ","
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
import java.io.File
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonNamingStrategy
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
class SavedPostSerializerTest {
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||
}
|
||||
private val text = getJson()
|
||||
|
||||
@Test
|
||||
fun serialize() {
|
||||
val encoded = json.encodeToString(SavedPostSerializer, SAVED_POST)
|
||||
assertThat(encoded).isNotEmpty()
|
||||
assertThat(encoded).isEqualTo(text)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deserialize() {
|
||||
val decoded = json.decodeFromString(SavedPostSerializer, text)
|
||||
assertThat(decoded).isEqualTo(SAVED_POST)
|
||||
}
|
||||
|
||||
private fun getJson(): String {
|
||||
// Load the JSON response
|
||||
val uri = javaClass.classLoader!!.getResource("saved_post.json")
|
||||
val file = File(uri.path)
|
||||
return String(file.readBytes())
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val SAVED_POST =
|
||||
SavedPost(
|
||||
title = "Fun Format Friday: You now have a super computer. What next?",
|
||||
shortId = "nbigsf",
|
||||
url = "",
|
||||
createdAt = "2023-05-04T23:43:50.000-05:00",
|
||||
commentCount = 13,
|
||||
commentsUrl = "https://lobste.rs/s/nbigsf/fun_format_friday_you_now_have_super",
|
||||
submitterName = "LenFalken",
|
||||
submitterAvatarUrl = "/avatars/LenFalken-100.png",
|
||||
tags = listOf("ask", "programming"),
|
||||
description =
|
||||
"<p>You suddenly have in your possession a super computer. What comes next? What projects are suddenly possible for you? What performance tests can you now explore?</p>\n",
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.local
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import java.util.UUID
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class PostCommentsQueriesTest {
|
||||
private lateinit var postQueries: PostCommentsQueries
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
postQueries = setupDatabase().postCommentsQueries
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get non-existent post`() {
|
||||
val ids = postQueries.getCommentIds(UUID.randomUUID().toString()).executeAsOneOrNull()
|
||||
assertThat(ids).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `put and get post comments`() {
|
||||
val postId = UUID.randomUUID().toString()
|
||||
val comments = PostComments(postId, List(10) { UUID.randomUUID().toString() })
|
||||
postQueries.rememberComments(comments)
|
||||
|
||||
val ids = postQueries.getCommentIds(postId).executeAsOne().commentIds
|
||||
assertThat(ids).hasSize(10)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.local
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import java.util.UUID
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ReadPostsQueriesTest {
|
||||
private lateinit var postQueries: ReadPostsQueries
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
postQueries = setupDatabase().readPostsQueries
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mark post as read`() {
|
||||
val id = UUID.randomUUID().toString()
|
||||
postQueries.markRead(id)
|
||||
assertThat(postQueries.isRead(id).executeAsOne()).isNotNull()
|
||||
postQueries.markUnread(id)
|
||||
assertThat(postQueries.isRead(id).executeAsOneOrNull()).isNull()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright © 2021-2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.local
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class SavedPostQueriesTest {
|
||||
private lateinit var postQueries: SavedPostQueries
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
postQueries = setupDatabase().savedPostQueries
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `add and count posts`() {
|
||||
val posts = createTestData(5)
|
||||
|
||||
posts.forEach { postQueries.insertOrReplacePost(it) }
|
||||
|
||||
val postCount = postQueries.selectCount().executeAsOne()
|
||||
|
||||
assertThat(postCount).isEqualTo(5)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `update post in database`() {
|
||||
// Get 1 post
|
||||
val post = createTestData(1)[0]
|
||||
|
||||
// Insert post into DB
|
||||
postQueries.insertOrReplacePost(post)
|
||||
|
||||
// Create a new post and try replacing it
|
||||
val newPost = post.copy(submitterName = "Fake name")
|
||||
postQueries.insertOrReplacePost(newPost)
|
||||
|
||||
// Check post count
|
||||
val postsCount = postQueries.selectCount().executeAsOne()
|
||||
assertThat(postsCount).isEqualTo(1)
|
||||
|
||||
// Check if post is updated
|
||||
val postFromDb = postQueries.selectPost(post.shortId).executeAsOne()
|
||||
|
||||
assertThat(postFromDb.submitterName).isEqualTo("Fake name")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get post from db`() {
|
||||
// Get 1 post
|
||||
val post = createTestData(1)[0]
|
||||
|
||||
// Insert post into DB
|
||||
postQueries.insertOrReplacePost(post)
|
||||
|
||||
val postFromDb = postQueries.selectAllPosts().executeAsOne()
|
||||
assertThat(postFromDb.shortId).isEqualTo("test_id_1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get multiple posts from db`() {
|
||||
// Get 5 post
|
||||
val posts = createTestData(5)
|
||||
|
||||
// Insert posts into DB
|
||||
posts.forEach { postQueries.insertOrReplacePost(it) }
|
||||
|
||||
val postsFromDb = postQueries.selectAllPosts().executeAsList()
|
||||
|
||||
// Check if all posts have correct shortId
|
||||
postsFromDb.forEachIndexed { index, post ->
|
||||
assertThat(post.shortId).isEqualTo("test_id_${index.inc()}")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `delete post`() {
|
||||
// Create 3 posts and insert them to DB
|
||||
val posts = createTestData(3)
|
||||
posts.forEach { postQueries.insertOrReplacePost(it) }
|
||||
|
||||
// Delete 2nd post
|
||||
postQueries.deletePost("test_id_2")
|
||||
|
||||
val postsFromDB = postQueries.selectAllPosts().executeAsList()
|
||||
|
||||
// Check if size is 2, and only the correct post is deleted
|
||||
assertThat(postsFromDB).hasSize(2)
|
||||
assertThat(postsFromDB[0].shortId).isEqualTo("test_id_1")
|
||||
assertThat(postsFromDB[1].shortId).isEqualTo("test_id_3")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `delete all posts`() {
|
||||
// Create 5 posts and insert them to DB
|
||||
val posts = createTestData(5)
|
||||
posts.forEach { postQueries.insertOrReplacePost(it) }
|
||||
|
||||
// Delete all posts
|
||||
postQueries.deleteAllPosts()
|
||||
|
||||
val dbPosts = postQueries.selectAllPosts().executeAsList()
|
||||
|
||||
assertThat(dbPosts).isEmpty()
|
||||
}
|
||||
|
||||
private fun createTestData(count: Int): ArrayList<SavedPost> {
|
||||
val posts = arrayListOf<SavedPost>()
|
||||
|
||||
for (i in 1..count) {
|
||||
val post =
|
||||
SavedPost(
|
||||
shortId = "test_id_$i",
|
||||
createdAt = "0",
|
||||
title = "test",
|
||||
url = "test_url",
|
||||
commentCount = 0,
|
||||
commentsUrl = "test_comments_url",
|
||||
submitterName = "test_user_$i",
|
||||
submitterAvatarUrl = "test_avatar_url",
|
||||
tags = listOf(),
|
||||
description = "",
|
||||
)
|
||||
|
||||
posts.add(post)
|
||||
}
|
||||
|
||||
return posts
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright © 2023 Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.database.local
|
||||
|
||||
import app.cash.sqldelight.adapter.primitive.IntColumnAdapter
|
||||
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
|
||||
import dev.msfjarvis.claw.database.LobstersDatabase
|
||||
import dev.msfjarvis.claw.database.model.CSVAdapter
|
||||
|
||||
fun setupDatabase(): LobstersDatabase {
|
||||
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
|
||||
LobstersDatabase.Schema.create(driver)
|
||||
return LobstersDatabase(
|
||||
driver,
|
||||
PostComments.Adapter(CSVAdapter()),
|
||||
SavedPost.Adapter(IntColumnAdapter, CSVAdapter()),
|
||||
)
|
||||
}
|
1
database/impl/src/test/resources/saved_post.json
Normal file
1
database/impl/src/test/resources/saved_post.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"short_id":"nbigsf","title":"Fun Format Friday: You now have a super computer. What next?","url":"","created_at":"2023-05-04T23:43:50.000-05:00","comment_count":13,"comments_url":"https://lobste.rs/s/nbigsf/fun_format_friday_you_now_have_super","submitter_name":"LenFalken","submitter_avatar_url":"/avatars/LenFalken-100.png","tags":["ask","programming"],"description":"<p>You suddenly have in your possession a super computer. What comes next? What projects are suddenly possible for you? What performance tests can you now explore?</p>\n"}
|
Loading…
Add table
Add a link
Reference in a new issue