diff --git a/core/database/src/androidMain/kotlin/club/nito/core/database/Database.android.kt b/core/database/src/androidMain/kotlin/club/nito/core/database/Database.android.kt new file mode 100644 index 00000000..abeb4280 --- /dev/null +++ b/core/database/src/androidMain/kotlin/club/nito/core/database/Database.android.kt @@ -0,0 +1,24 @@ +package club.nito.core.database + +import android.content.Context +import androidx.sqlite.db.SupportSQLiteDatabase +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.android.AndroidSqliteDriver + +internal actual class DriverFactory(private val context: Context) { + actual fun createDriver(): SqlDriver { + val schema = Database.Schema + + return AndroidSqliteDriver( + schema = schema, + context = context, + name = DATABASE_NAME, + callback = object : AndroidSqliteDriver.Callback(schema) { + override fun onConfigure(db: SupportSQLiteDatabase) { + db.enableWriteAheadLogging() + db.setForeignKeyConstraintsEnabled(true) + } + }, + ) + } +} diff --git a/core/database/src/androidMain/kotlin/club/nito/core/database/di/DatabaseModule.android.kt b/core/database/src/androidMain/kotlin/club/nito/core/database/di/DatabaseModule.android.kt new file mode 100644 index 00000000..78c667b3 --- /dev/null +++ b/core/database/src/androidMain/kotlin/club/nito/core/database/di/DatabaseModule.android.kt @@ -0,0 +1,8 @@ +package club.nito.core.database.di + +import club.nito.core.database.DriverFactory +import org.koin.core.scope.Scope + +internal actual fun Scope.createDriverFactory(): DriverFactory = DriverFactory( + context = get(), +) diff --git a/core/database/src/commonMain/kotlin/club/nito/core/database/.gitkeep b/core/database/src/commonMain/kotlin/club/nito/core/database/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/core/database/src/commonMain/kotlin/club/nito/core/database/Database.kt b/core/database/src/commonMain/kotlin/club/nito/core/database/Database.kt new file mode 100644 index 00000000..2cd38947 --- /dev/null +++ b/core/database/src/commonMain/kotlin/club/nito/core/database/Database.kt @@ -0,0 +1,23 @@ +package club.nito.core.database + +import app.cash.sqldelight.EnumColumnAdapter +import app.cash.sqldelight.db.SqlDriver + +internal expect class DriverFactory { + fun createDriver(): SqlDriver +} + +internal const val DATABASE_NAME = "nito.db" + +internal fun createDatabase(driverFactory: DriverFactory): Database { + val driver = driverFactory.createDriver() + val database = Database( + driver = driver, + participantsAdapter = Participants.Adapter( + statusAdapter = EnumColumnAdapter(), + ), + ) + + // Do more work with the database (see below). + return database +} diff --git a/core/database/src/commonMain/kotlin/club/nito/core/database/adapter/ParticipantStatus.kt b/core/database/src/commonMain/kotlin/club/nito/core/database/adapter/ParticipantStatus.kt new file mode 100644 index 00000000..c7603e72 --- /dev/null +++ b/core/database/src/commonMain/kotlin/club/nito/core/database/adapter/ParticipantStatus.kt @@ -0,0 +1,10 @@ +package club.nito.core.database.adapter + +import app.cash.sqldelight.ColumnAdapter +import club.nito.core.model.participant.ParticipantStatus + +internal data object ParticipantStatusAdapter : ColumnAdapter { + override fun decode(databaseValue: String): ParticipantStatus = ParticipantStatus.valueOf(databaseValue) + + override fun encode(value: ParticipantStatus): String = value.name +} diff --git a/core/database/src/commonMain/kotlin/club/nito/core/database/di/DatabaseModule.kt b/core/database/src/commonMain/kotlin/club/nito/core/database/di/DatabaseModule.kt new file mode 100644 index 00000000..d0f557b7 --- /dev/null +++ b/core/database/src/commonMain/kotlin/club/nito/core/database/di/DatabaseModule.kt @@ -0,0 +1,17 @@ +package club.nito.core.database.di + +import club.nito.core.database.DriverFactory +import club.nito.core.database.createDatabase +import org.koin.core.module.Module +import org.koin.core.scope.Scope +import org.koin.dsl.module + +public val databaseModule: Module = module { + single { + createDatabase( + driverFactory = createDriverFactory(), + ) + } +} + +internal expect fun Scope.createDriverFactory(): DriverFactory diff --git a/core/database/src/commonMain/sqldelight/club/nito/core/database/Participants.sq b/core/database/src/commonMain/sqldelight/club/nito/core/database/Participants.sq new file mode 100644 index 00000000..80eb56bd --- /dev/null +++ b/core/database/src/commonMain/sqldelight/club/nito/core/database/Participants.sq @@ -0,0 +1,37 @@ +import club.nito.core.model.participant.ParticipantStatus; + +CREATE TABLE `participants` ( + `schedule_id` TEXT NOT NULL, + `user_id` TEXT NOT NULL, + `status` TEXT AS ParticipantStatus NOT NULL +); + +CREATE UNIQUE INDEX `participants_pkey` ON `participants` (`schedule_id`, `user_id`); + +participantsByScheduleId: +SELECT * +FROM participants +WHERE schedule_id = ?; + +participantsByUserId: +SELECT * +FROM participants +WHERE user_id = ?; + +upsert { + UPDATE participants SET + `schedule_id` = :schedule_id, + `user_id` = :user_id, + `status` = :status + WHERE schedule_id = :schedule_id AND user_id = :user_id; + + INSERT OR IGNORE INTO participants ( + `schedule_id`, + `user_id`, + `status` + ) VALUES ( + :schedule_id, + :user_id, + :status + ); +} diff --git a/core/database/src/androidMain/kotlin/club/nito/core/database/.gitkeep b/core/database/src/commonMain/sqldelight/migrations/1.sqm similarity index 100% rename from core/database/src/androidMain/kotlin/club/nito/core/database/.gitkeep rename to core/database/src/commonMain/sqldelight/migrations/1.sqm diff --git a/core/database/src/iosMain/kotlin/club/nito/core/database/.gitkeep b/core/database/src/iosMain/kotlin/club/nito/core/database/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/core/database/src/iosMain/kotlin/club/nito/core/database/Database.ios.kt b/core/database/src/iosMain/kotlin/club/nito/core/database/Database.ios.kt new file mode 100644 index 00000000..b2ac0750 --- /dev/null +++ b/core/database/src/iosMain/kotlin/club/nito/core/database/Database.ios.kt @@ -0,0 +1,11 @@ +package club.nito.core.database + +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.native.NativeSqliteDriver + +internal actual class DriverFactory { + actual fun createDriver(): SqlDriver = NativeSqliteDriver( + schema = Database.Schema, + name = DATABASE_NAME, + ) +} diff --git a/core/database/src/iosMain/kotlin/club/nito/core/database/di/DatabaseModule.ios.kt b/core/database/src/iosMain/kotlin/club/nito/core/database/di/DatabaseModule.ios.kt new file mode 100644 index 00000000..10d00dd6 --- /dev/null +++ b/core/database/src/iosMain/kotlin/club/nito/core/database/di/DatabaseModule.ios.kt @@ -0,0 +1,6 @@ +package club.nito.core.database.di + +import club.nito.core.database.DriverFactory +import org.koin.core.scope.Scope + +internal actual fun Scope.createDriverFactory(): DriverFactory = DriverFactory() diff --git a/core/database/src/jsMain/kotlin/club/nito/core/database/Database.js.kt b/core/database/src/jsMain/kotlin/club/nito/core/database/Database.js.kt new file mode 100644 index 00000000..8d9506ba --- /dev/null +++ b/core/database/src/jsMain/kotlin/club/nito/core/database/Database.js.kt @@ -0,0 +1,15 @@ +package club.nito.core.database + +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.worker.WebWorkerDriver +import org.w3c.dom.Worker + +internal actual class DriverFactory { + actual fun createDriver(): SqlDriver { + return WebWorkerDriver( + Worker( + js("""new URL("@cashapp/sqldelight-sqljs-worker/sqljs.worker.js", import.meta.url)""") + ) + ).also { Database.Schema.create(it) } + } +} diff --git a/core/database/src/jsMain/kotlin/club/nito/core/database/di/DatabaseModule.js.kt b/core/database/src/jsMain/kotlin/club/nito/core/database/di/DatabaseModule.js.kt new file mode 100644 index 00000000..10d00dd6 --- /dev/null +++ b/core/database/src/jsMain/kotlin/club/nito/core/database/di/DatabaseModule.js.kt @@ -0,0 +1,6 @@ +package club.nito.core.database.di + +import club.nito.core.database.DriverFactory +import org.koin.core.scope.Scope + +internal actual fun Scope.createDriverFactory(): DriverFactory = DriverFactory()