Skip to content

Commit

Permalink
Merge pull request #147 from 2rabs/rt/add-daos
Browse files Browse the repository at this point in the history
✨ Dao を追加
  • Loading branch information
tatsutakein authored Dec 12, 2023
2 parents a45bf0e + 8127097 commit 081000c
Show file tree
Hide file tree
Showing 29 changed files with 749 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package club.nito.core.database

import app.cash.sqldelight.EnumColumnAdapter
import app.cash.sqldelight.db.SqlDriver
import club.nito.core.database.adapter.InstantLongColumnAdapter

internal expect class DriverFactory {
fun createDriver(): SqlDriver
Expand All @@ -16,6 +17,10 @@ internal fun createDatabase(driverFactory: DriverFactory): Database {
participantsAdapter = Participants.Adapter(
statusAdapter = EnumColumnAdapter(),
),
schedulesAdapter = Schedules.Adapter(
scheduled_atAdapter = InstantLongColumnAdapter,
met_atAdapter = InstantLongColumnAdapter,
),
)

// Do more work with the database (see below).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package club.nito.core.database.adapter

import app.cash.sqldelight.ColumnAdapter
import kotlinx.datetime.Instant

internal object InstantLongColumnAdapter : ColumnAdapter<Instant, Long> {
override fun decode(databaseValue: Long): Instant = Instant.fromEpochMilliseconds(databaseValue)
override fun encode(value: Instant): Long = value.toEpochMilliseconds()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ package club.nito.core.database.di

import club.nito.core.database.DriverFactory
import club.nito.core.database.createDatabase
import club.nito.core.database.participant.ParticipantDao
import club.nito.core.database.participant.SqlDelightParticipantDao
import club.nito.core.database.place.PlaceDao
import club.nito.core.database.place.SqlDelightPlaceDao
import club.nito.core.database.profile.ProfileDao
import club.nito.core.database.profile.SqlDelightProfileDao
import club.nito.core.database.schedule.ScheduleDao
import club.nito.core.database.schedule.SqlDelightScheduleDao
import org.koin.core.module.Module
import org.koin.core.module.dsl.singleOf
import org.koin.core.scope.Scope
import org.koin.dsl.bind
import org.koin.dsl.module

public val databaseModule: Module = module {
Expand All @@ -12,6 +22,11 @@ public val databaseModule: Module = module {
driverFactory = createDriverFactory(),
)
}

singleOf(::SqlDelightParticipantDao) bind ParticipantDao::class
singleOf(::SqlDelightPlaceDao) bind PlaceDao::class
singleOf(::SqlDelightProfileDao) bind ProfileDao::class
singleOf(::SqlDelightScheduleDao) bind ScheduleDao::class
}

internal expect fun Scope.createDriverFactory(): DriverFactory
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package club.nito.core.database.participant

import club.nito.core.model.participant.Participant
import club.nito.core.model.participant.ParticipantStatus
import club.nito.core.model.participant.ParticipantUser
import kotlinx.coroutines.flow.Flow

public interface ParticipantDao {
/**
* 該当の予定の参加情報のストリームを取得する
*
* @param scheduleId 参加情報を取得するスケジュールID
*/
public fun participantUsersStream(scheduleId: String): Flow<List<ParticipantUser>>

/**
* 該当の予定の参加情報のストリームを取得する
*
* @param scheduleId 参加情報を取得するスケジュールID
*/
public fun participantStatusStream(scheduleId: String, userId: String): Flow<ParticipantStatus>

/**
* 参加者を登録 / 更新する
*/
public fun upsert(entities: List<Participant>)

/**
* 参加者を登録 / 更新する
*/
public fun upsert(entity: Participant)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package club.nito.core.database.participant

import app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import app.cash.sqldelight.coroutines.mapToOneOrNull
import club.nito.core.common.NitoCoroutineDispatchers
import club.nito.core.database.Database
import club.nito.core.database.ParticipantUsersByScheduleId
import club.nito.core.database.participant.model.toModel
import club.nito.core.model.participant.Participant
import club.nito.core.model.participant.ParticipantStatus
import club.nito.core.model.participant.ParticipantUser
import club.nito.core.model.schedule.ScheduleId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

internal class SqlDelightParticipantDao(
private val database: Database,
private val dispatchers: NitoCoroutineDispatchers,
) : ParticipantDao {
override fun participantUsersStream(scheduleId: ScheduleId): Flow<List<ParticipantUser>> {
return database.participantsQueries.participantUsersByScheduleId(scheduleId)
.asFlow()
.mapToList(dispatchers.io)
.map {
it.map(ParticipantUsersByScheduleId::toModel)
}
}

override fun participantStatusStream(scheduleId: String, userId: String): Flow<ParticipantStatus> = database
.participantsQueries
.participantStatusByUserId(
schedule_id = scheduleId,
user_id = userId,
)
.asFlow()
.mapToOneOrNull(dispatchers.io)
.map {
it ?: ParticipantStatus.NONE
}

override fun upsert(entities: List<Participant>) {
database.transaction {
for (entity in entities) {
upsertParticipant(entity)
}
}
}

override fun upsert(entity: Participant) {
database.transaction {
upsertParticipant(entity)
}
}

private fun upsertParticipant(entity: Participant) {
database.participantsQueries.upsert(
schedule_id = entity.scheduleId,
user_id = entity.userId,
status = entity.status,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package club.nito.core.database.adapter
package club.nito.core.database.participant.adapter

import app.cash.sqldelight.ColumnAdapter
import club.nito.core.model.participant.ParticipantStatus
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package club.nito.core.database.participant.model

import club.nito.core.model.UserProfile
import club.nito.core.model.participant.Participant
import club.nito.core.model.participant.ParticipantUser
import club.nito.core.database.ParticipantUsersByScheduleId as LocalParticipantUser
import club.nito.core.database.Participants as LocalParticipant

internal fun LocalParticipant.toModel(): Participant = Participant(
scheduleId = schedule_id,
userId = user_id,
status = status,
)

internal fun LocalParticipantUser.toModel(): ParticipantUser = ParticipantUser(
profile = UserProfile(
id = id,
username = username,
displayName = display_name,
avatarUrl = avatar_url,
website = website,
),
status = status,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package club.nito.core.database.place

import club.nito.core.model.place.Place
import kotlinx.coroutines.flow.Flow

public interface PlaceDao {
/**
* 場所一覧のストリームを取得する
*/
public val placesStream: Flow<List<Place>>

/**
* 場所のストリームを取得する
*
* @param placeId 取得する場所の ID
*/
public fun placeStream(placeId: String): Flow<Place?>

/**
* 場所一覧のストリームを取得する
*
* @param placeIds 取得する場所の ID 配列
*/
public fun placesStream(placeIds: List<String>): Flow<List<Place>>

/**
* 場所一覧を登録 / 更新する
*/
public fun upsert(entities: List<Place>)

/**
* 場所を登録 / 更新する
*/
public fun upsert(entity: Place)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package club.nito.core.database.place

import app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import app.cash.sqldelight.coroutines.mapToOneOrNull
import club.nito.core.common.NitoCoroutineDispatchers
import club.nito.core.database.Database
import club.nito.core.database.Places
import club.nito.core.database.place.model.toModel
import club.nito.core.model.place.Place
import club.nito.core.model.schedule.ScheduleId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

internal class SqlDelightPlaceDao(
private val database: Database,
private val dispatchers: NitoCoroutineDispatchers,
) : PlaceDao {
override val placesStream: Flow<List<Place>>
get() = database.placesQueries.places()
.asFlow()
.mapToList(dispatchers.io)
.map {
it.map(Places::toModel)
}

override fun placeStream(placeId: ScheduleId): Flow<Place?> {
return database.placesQueries.placeById(placeId)
.asFlow()
.mapToOneOrNull(dispatchers.io)
.map {
it?.toModel()
}
}

override fun placesStream(placeIds: List<String>): Flow<List<Place>> {
return database.placesQueries.placesByIds(placeIds)
.asFlow()
.mapToList(dispatchers.io)
.map {
it.map(Places::toModel)
}
}

override fun upsert(entities: List<Place>) {
database.transaction {
for (entity in entities) {
upsertPlace(entity)
}
}
}

override fun upsert(entity: Place) {
database.transaction {
upsertPlace(entity)
}
}

private fun upsertPlace(entity: Place) {
database.placesQueries.upsert(
id = entity.id,
name = entity.name,
url = entity.url,
description = entity.description,
map_url = entity.mapUrl,
image_url = entity.imageUrl,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package club.nito.core.database.place.model

import club.nito.core.model.place.Place
import club.nito.core.database.Places as LocalPlace

internal fun LocalPlace.toModel(): Place = Place(
id = id,
name = name,
url = url,
description = description,
mapUrl = map_url,
imageUrl = image_url,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package club.nito.core.database.profile

import club.nito.core.model.UserProfile
import kotlinx.coroutines.flow.Flow

public interface ProfileDao {
/**
* ユーザー情報のストリームを取得する
*
* @param userId 取得するユーザーの ID
*/
public fun profileStream(userId: String): Flow<UserProfile?>

/**
* ユーザー情報のストリームを取得する
*
* @param userIds 取得するユーザーの ID 配列
*/
public fun profilesStream(userIds: List<String>): Flow<List<UserProfile>>

/**
* ユーザー一覧を登録 / 更新する
*/
public fun upsert(entities: List<UserProfile>)

/**
* ユーザーを登録 / 更新する
*/
public fun upsert(entity: UserProfile)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package club.nito.core.database.profile

import app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import app.cash.sqldelight.coroutines.mapToOneOrNull
import club.nito.core.common.NitoCoroutineDispatchers
import club.nito.core.database.Database
import club.nito.core.database.Profiles
import club.nito.core.database.profile.model.toModel
import club.nito.core.model.UserProfile
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

internal class SqlDelightProfileDao(
private val database: Database,
private val dispatchers: NitoCoroutineDispatchers,
) : ProfileDao {
override fun profileStream(userId: String): Flow<UserProfile?> {
return database.profilesQueries.profileById(userId)
.asFlow()
.mapToOneOrNull(dispatchers.io)
.map {
it?.toModel()
}
}

override fun profilesStream(userIds: List<String>): Flow<List<UserProfile>> {
return database.profilesQueries.profileByIds(userIds)
.asFlow()
.mapToList(dispatchers.io)
.map {
it.map(Profiles::toModel)
}
}

override fun upsert(entities: List<UserProfile>) {
database.transaction {
for (entity in entities) {
upsertUserProfile(entity)
}
}
}

override fun upsert(entity: UserProfile) {
database.transaction {
upsertUserProfile(entity)
}
}

private fun upsertUserProfile(entity: UserProfile) {
database.profilesQueries.upsert(
id = entity.id,
username = entity.username,
display_name = entity.displayName,
avatar_url = entity.avatarUrl,
website = entity.website,
)
}
}
Loading

0 comments on commit 081000c

Please sign in to comment.