From a86da9d95b24f8e048a257024a3096e48683a507 Mon Sep 17 00:00:00 2001 From: Artur Babichev Date: Sat, 13 Sep 2025 10:22:33 +0400 Subject: [PATCH 1/3] feat(jvm): add sqlite-mc encryption --- core/data/db-sqldelight/build.gradle.kts | 6 +- .../notedelight/db/JdbcDatabaseHolder.kt | 15 ++- .../notedelight/db/JvmCipherUtils.kt | 106 +++++------------- .../notedelight/repository/JvmSafeRepo.kt | 22 ++-- .../notedelight/db/JvmCipherUtilsTest.kt | 3 +- .../notedelight/ui/DesktopUiTests.kt | 2 - gradle/libs.versions.toml | 2 + 7 files changed, 45 insertions(+), 111 deletions(-) diff --git a/core/data/db-sqldelight/build.gradle.kts b/core/data/db-sqldelight/build.gradle.kts index 00647267..913d581e 100644 --- a/core/data/db-sqldelight/build.gradle.kts +++ b/core/data/db-sqldelight/build.gradle.kts @@ -4,7 +4,7 @@ plugins { alias(libs.plugins.gradle.convention) alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.library) - alias(libs.plugins.sqlDelight) + id("io.toxicity.sqlite-mc") version "2.1.0-2.2.3-0" alias(libs.plugins.kotlin.cocoapods) } @@ -53,7 +53,6 @@ kotlin { iosTest.dependencies { } jvmMain.dependencies { - implementation(libs.sqlDelight.jvm) implementation(libs.appdirs) implementation(libs.napier) } @@ -91,11 +90,10 @@ android { testOptions.unitTests.isReturnDefaultValues = true } -sqldelight { +sqliteMC { databases { create("NoteDb") { packageName.set("com.softartdev.notedelight.db") } } - linkSqlite.set(false) } diff --git a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JdbcDatabaseHolder.kt b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JdbcDatabaseHolder.kt index b81d6e88..2f70e481 100644 --- a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JdbcDatabaseHolder.kt +++ b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JdbcDatabaseHolder.kt @@ -1,15 +1,14 @@ package com.softartdev.notedelight.db -import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver import io.github.aakira.napier.Napier +import io.toxicity.sqlite.mc.driver.SQLiteMCDriver import java.sql.SQLException -import java.util.Properties -class JdbcDatabaseHolder(props: Properties = Properties()) : SqlDelightDbHolder { - override val driver = JdbcSqliteDriver( - url = JdbcSqliteDriver.IN_MEMORY + FilePathResolver().invoke(),// jdbc:sqlite:/.../notes.db - properties = props - ) +class JdbcDatabaseHolder( + passphrase: CharSequence = "", + rekey: CharSequence? = null, +) : SqlDelightDbHolder { + override val driver: SQLiteMCDriver = JvmCipherUtils.createDriver(passphrase, rekey) override val noteDb: NoteDb = createQueryWrapper(driver) override val noteQueries = noteDb.noteQueries @@ -39,4 +38,4 @@ class JdbcDatabaseHolder(props: Properties = Properties()) : SqlDelightDbHolder } override fun close() = driver.close() -} \ No newline at end of file +} diff --git a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JvmCipherUtils.kt b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JvmCipherUtils.kt index 1b85b70b..94238192 100644 --- a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JvmCipherUtils.kt +++ b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JvmCipherUtils.kt @@ -1,96 +1,42 @@ package com.softartdev.notedelight.db -import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver import com.softartdev.notedelight.model.PlatformSQLiteState +import io.toxicity.sqlite.mc.driver.SQLiteMCDriver +import io.toxicity.sqlite.mc.driver.config.DatabasesDir +import io.toxicity.sqlite.mc.driver.config.encryption.Key import java.io.File -import java.io.FileNotFoundException -import java.sql.Connection -import java.sql.DriverManager -import java.sql.ResultSet -import java.sql.Statement object JvmCipherUtils { - - fun getDatabaseState(dbName: String): PlatformSQLiteState { - var result = PlatformSQLiteState.DOES_NOT_EXIST - val dbPath = File(dbName) - if (dbPath.exists()) { - result = PlatformSQLiteState.UNENCRYPTED - var connection: Connection? = null - try { - val url = JdbcSqliteDriver.IN_MEMORY + dbName // jdbc:sqlite:$dbName - connection = DriverManager.getConnection(url) - val statement: Statement = connection.createStatement() - val resultSet: ResultSet = statement.executeQuery("PRAGMA user_version;") - val version: Long = resultSet.getLong(1) - println("db version = $version") - } catch (throwable: Throwable) { - throwable.printStackTrace() - result = PlatformSQLiteState.ENCRYPTED - } finally { - connection?.close() + private val dbFile = File(FilePathResolver().invoke()) + + private val factory = SQLiteMCDriver.Factory( + dbName = dbFile.name, + schema = NoteDb.Schema + ) { + filesystem(DatabasesDir(dbFile.parentFile!!)) { + encryption { + sqlCipher { v4() } } } - return result } - fun decrypt(password: String, dbName: String) { - val originalFile = File(dbName) - if (originalFile.exists()) { - val newFile = File.createTempFile("sqlcipherutils", "tmp", null) - - var url = JdbcSqliteDriver.IN_MEMORY + dbName // jdbc:sqlite:$dbName - var connection = DriverManager.getConnection(url, null, password) - val statement = connection.prepareStatement("ATTACH DATABASE ? AS plaintext KEY ''") - statement.setString(1, newFile.absolutePath) - statement.execute() - connection.createStatement().executeQuery("SELECT sqlcipher_export('plaintext')") - connection.createStatement().executeQuery("DETACH DATABASE plaintext") - val resultSet: ResultSet = statement.executeQuery("PRAGMA user_version;") - val version: Long = resultSet.getLong(1) - statement.close() - connection.close() - - url = JdbcSqliteDriver.IN_MEMORY + newFile.absolutePath - connection = DriverManager.getConnection(url) - connection.createStatement().executeQuery("PRAGMA user_version = $version") - connection.close() - - originalFile.delete() - newFile.renameTo(originalFile) - } else { - throw FileNotFoundException(originalFile.absolutePath + " not found") + fun getDatabaseState(): PlatformSQLiteState { + if (!dbFile.exists()) return PlatformSQLiteState.DOES_NOT_EXIST + return try { + factory.createBlocking(Key.Empty).close() + PlatformSQLiteState.UNENCRYPTED + } catch (_: Throwable) { + PlatformSQLiteState.ENCRYPTED } } - fun encrypt(password: String?, dbName: String) { - val originalFile = File(dbName) - if (originalFile.exists()) { - val newFile = File.createTempFile("sqlcipherutils", "tmp", null) - - var url = JdbcSqliteDriver.IN_MEMORY + originalFile.absolutePath // jdbc:sqlite:${originalFile.absolutePath} - var connection = DriverManager.getConnection(url) - var statement: Statement = connection.createStatement() - val resultSet: ResultSet = statement.executeQuery("PRAGMA user_version;") - val version: Long = resultSet.getLong(1) - statement.close() - connection.close() - - url = JdbcSqliteDriver.IN_MEMORY + newFile.absolutePath - connection = DriverManager.getConnection(url, null, password) - statement = connection.prepareStatement("ATTACH DATABASE ? AS plaintext KEY ''") - statement.setString(1, originalFile.absolutePath) - statement.execute() - connection.createStatement().executeQuery("SELECT sqlcipher_export('plaintext')") - connection.createStatement().executeQuery("DETACH DATABASE plaintext") - connection.createStatement().executeQuery("PRAGMA user_version = $version") - statement.close() - connection.close() - - originalFile.delete() - newFile.renameTo(originalFile) + fun createDriver(passphrase: CharSequence = "", rekey: CharSequence? = null): SQLiteMCDriver { + val key = if (passphrase.isEmpty()) Key.Empty else Key.passphrase(passphrase.toString()) + return if (rekey != null) { + val rekeyKey = if (rekey.isEmpty()) Key.Empty else Key.passphrase(rekey.toString()) + factory.createBlocking(key, rekeyKey) } else { - throw FileNotFoundException(originalFile.absolutePath + " not found") + factory.createBlocking(key) } } -} \ No newline at end of file +} diff --git a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/repository/JvmSafeRepo.kt b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/repository/JvmSafeRepo.kt index 56b5f905..3c36fd62 100644 --- a/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/repository/JvmSafeRepo.kt +++ b/core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/repository/JvmSafeRepo.kt @@ -8,14 +8,13 @@ import com.softartdev.notedelight.db.JvmCipherUtils import com.softartdev.notedelight.db.NoteDAO import com.softartdev.notedelight.db.SqlDelightNoteDAO import com.softartdev.notedelight.model.PlatformSQLiteState -import java.util.Properties class JvmSafeRepo : SafeRepo() { @Volatile private var databaseHolder: JdbcDatabaseHolder? = null override val databaseState: PlatformSQLiteState - get() = JvmCipherUtils.getDatabaseState(DB_NAME) + get() = JvmCipherUtils.getDatabaseState() override val noteDAO: NoteDAO get() = SqlDelightNoteDAO(buildDbIfNeed().noteQueries) @@ -26,9 +25,7 @@ class JvmSafeRepo : SafeRepo() { override fun buildDbIfNeed(passphrase: CharSequence): JdbcDatabaseHolder { var instance = databaseHolder if (instance == null) { - val properties = Properties() - if (passphrase.isNotEmpty()) properties["password"] = StringBuilder(passphrase).toString() - instance = JdbcDatabaseHolder(properties) + instance = JdbcDatabaseHolder(passphrase) databaseHolder = instance } return instance @@ -36,16 +33,14 @@ class JvmSafeRepo : SafeRepo() { override fun decrypt(oldPass: CharSequence) { closeDatabase() - JvmCipherUtils.decrypt( - password = StringBuilder(oldPass).toString(), - dbName = DB_NAME - ) + JdbcDatabaseHolder(oldPass, "").close() buildDbIfNeed() } override fun rekey(oldPass: CharSequence, newPass: CharSequence) { - decrypt(oldPass) - encrypt(newPass) + closeDatabase() + JdbcDatabaseHolder(oldPass, newPass).close() + buildDbIfNeed(newPass) } override fun execute(query: String): String? { @@ -65,10 +60,7 @@ class JvmSafeRepo : SafeRepo() { override fun encrypt(newPass: CharSequence) { closeDatabase() - JvmCipherUtils.encrypt( - password = StringBuilder(newPass).toString(), - dbName = DB_NAME - ) + JdbcDatabaseHolder("", newPass).close() buildDbIfNeed(newPass) } diff --git a/core/data/db-sqldelight/src/jvmTest/kotlin/com/softartdev/notedelight/db/JvmCipherUtilsTest.kt b/core/data/db-sqldelight/src/jvmTest/kotlin/com/softartdev/notedelight/db/JvmCipherUtilsTest.kt index 5c224764..51f42709 100644 --- a/core/data/db-sqldelight/src/jvmTest/kotlin/com/softartdev/notedelight/db/JvmCipherUtilsTest.kt +++ b/core/data/db-sqldelight/src/jvmTest/kotlin/com/softartdev/notedelight/db/JvmCipherUtilsTest.kt @@ -1,7 +1,6 @@ package com.softartdev.notedelight.db import com.softartdev.notedelight.model.PlatformSQLiteState -import com.softartdev.notedelight.repository.SafeRepo.Companion.DB_NAME import kotlin.test.* class JvmCipherUtilsTest { @@ -17,7 +16,7 @@ class JvmCipherUtilsTest { @Test fun getDatabaseState() { val exp = PlatformSQLiteState.ENCRYPTED - val act = JvmCipherUtils.getDatabaseState(DB_NAME) + val act = JvmCipherUtils.getDatabaseState() assertNotEquals(exp, act) } } \ No newline at end of file diff --git a/desktop-compose-app/src/jvmTest/kotlin/com/softartdev/notedelight/ui/DesktopUiTests.kt b/desktop-compose-app/src/jvmTest/kotlin/com/softartdev/notedelight/ui/DesktopUiTests.kt index d246a991..7d37a170 100644 --- a/desktop-compose-app/src/jvmTest/kotlin/com/softartdev/notedelight/ui/DesktopUiTests.kt +++ b/desktop-compose-app/src/jvmTest/kotlin/com/softartdev/notedelight/ui/DesktopUiTests.kt @@ -78,11 +78,9 @@ class DesktopUiTests : AbstractUiTests() { @Test override fun prepopulateDatabase() = super.prepopulateDatabase() - @Ignore("Desktop app doesn't support encryption yet") @Test override fun flowAfterCryptTest() = super.flowAfterCryptTest() - @Ignore("Desktop app doesn't support encryption yet") @Test override fun settingPasswordTest() = super.settingPasswordTest() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7baf4aa2..e59e8d2e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,6 +45,7 @@ desugar = "2.1.5" androidSecurityLint = "1.0.3" appdirs = "1.4.0" uiTooling = "1.9.1" +sqliteMc = "2.1.0-2.2.3-0" [libraries] coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "coroutines" } @@ -60,6 +61,7 @@ sqlDelight-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = " sqlDelight-paging = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqlDelight" } sqlDelight-coroutinesExt = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" } + stately-common = { module = "co.touchlab:stately-common", version.ref = "stately" } #FIXME https://github.com/cashapp/sqldelight/issues/4357 stately-isolate = { module = "co.touchlab:stately-isolate", version.ref = "stately" } stately-iso-collections = { module = "co.touchlab:stately-iso-collections", version.ref = "stately" } From f8452042d4bada91fc4081aa283e2f1536ba980b Mon Sep 17 00:00:00 2001 From: Artur Babichev Date: Sat, 13 Sep 2025 12:37:25 +0400 Subject: [PATCH 2/3] Remove lastInsertRowId query from Note.sq This commit removes the `lastInsertRowId` query from the `Note.sq` SQLDelight file. --- .../sqldelight/com/softartdev/notedelight/shared/db/Note.sq | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/data/db-sqldelight/src/commonMain/sqldelight/com/softartdev/notedelight/shared/db/Note.sq b/core/data/db-sqldelight/src/commonMain/sqldelight/com/softartdev/notedelight/shared/db/Note.sq index 5cf60ab2..7288adfb 100644 --- a/core/data/db-sqldelight/src/commonMain/sqldelight/com/softartdev/notedelight/shared/db/Note.sq +++ b/core/data/db-sqldelight/src/commonMain/sqldelight/com/softartdev/notedelight/shared/db/Note.sq @@ -23,9 +23,6 @@ SELECT * FROM note WHERE id = :noteId; insert: INSERT INTO note VALUES ?; -lastInsertRowId: -SELECT last_insert_rowid(); - update: INSERT OR REPLACE INTO note VALUES ?; From 2f6f326c53eaa78e5ff5fdab3538a164f08fbde6 Mon Sep 17 00:00:00 2001 From: Artur Babichev Date: Sun, 14 Sep 2025 03:17:10 +0400 Subject: [PATCH 3/3] Replace SQLDelight with SQLiteMC This commit replaces the SQLDelight database library with SQLiteMC. The changes include: - Updating plugin aliases in `build.gradle.kts` and `core/data/db-sqldelight/build.gradle.kts`. - Replacing SQLDelight dependencies with SQLiteMC dependencies in `gradle/libs.versions.toml`, `android-compose-app/build.gradle.kts`, and `core/data/db-sqldelight/build.gradle.kts`. - Updating the version catalog (`gradle/libs.versions.toml`) to reflect the new SQLiteMC version and remove the old SQLDelight version. - Commenting out SQLDelight specific dependencies and configurations. --- android-compose-app/build.gradle.kts | 3 ++- build.gradle.kts | 3 ++- core/data/db-sqldelight/build.gradle.kts | 19 ++++++++++++------ gradle/libs.versions.toml | 25 +++++++++++++++--------- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/android-compose-app/build.gradle.kts b/android-compose-app/build.gradle.kts index 40c802ec..8a0ab857 100644 --- a/android-compose-app/build.gradle.kts +++ b/android-compose-app/build.gradle.kts @@ -98,7 +98,8 @@ dependencies { exclude(group = "org.jetbrains.runtime", module = "jbr-api") } androidTestImplementation(libs.commonsware.saferoom) - androidTestImplementation(libs.sqlDelight.android) +// androidTestImplementation(libs.sqlDelight.android) + androidTestImplementation(libs.sqliteMc.android) androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.runner) androidTestUtil(libs.androidx.test.orchestrator) diff --git a/build.gradle.kts b/build.gradle.kts index ba26ca7f..15a88b29 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,8 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false - alias(libs.plugins.sqlDelight) apply false +// alias(libs.plugins.sqlDelight) apply false + alias(libs.plugins.sqliteMc) apply false alias(libs.plugins.room) apply false alias(libs.plugins.gms) apply false alias(libs.plugins.crashlytics) apply false diff --git a/core/data/db-sqldelight/build.gradle.kts b/core/data/db-sqldelight/build.gradle.kts index 913d581e..f211399e 100644 --- a/core/data/db-sqldelight/build.gradle.kts +++ b/core/data/db-sqldelight/build.gradle.kts @@ -4,7 +4,8 @@ plugins { alias(libs.plugins.gradle.convention) alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.library) - id("io.toxicity.sqlite-mc") version "2.1.0-2.2.3-0" +// alias(libs.plugins.sqlDelight) + alias(libs.plugins.sqliteMc) alias(libs.plugins.kotlin.cocoapods) } @@ -18,9 +19,12 @@ kotlin { sourceSets { commonMain.dependencies { implementation(project(":core:domain")) - implementation(libs.sqlDelight.runtime) + /*implementation(libs.sqlDelight.runtime) implementation(libs.sqlDelight.coroutinesExt) - implementation(libs.sqlDelight.paging) + implementation(libs.sqlDelight.paging)*/ +// implementation(libs.sqliteMc.runtime) +// implementation(libs.sqliteMc.coroutinesExt) +// implementation(libs.sqliteMc.paging) implementation(libs.kotlinx.datetime) implementation(libs.stately.common) } @@ -32,21 +36,24 @@ kotlin { implementation(libs.napier) } androidMain.dependencies { - implementation(libs.sqlDelight.android) +// implementation(libs.sqlDelight.android) +// implementation(libs.sqliteMc.android) implementation(libs.commonsware.saferoom) implementation(libs.android.sqlcipher) } androidUnitTest.dependencies { implementation(kotlin("test-junit")) implementation(libs.bundles.mockito) - implementation(libs.sqlDelight.jvm) +// implementation(libs.sqlDelight.jvm) +// implementation(libs.sqliteMc.jvm) } androidInstrumentedTest.dependencies { implementation(libs.androidx.test.ext.junit) implementation(libs.androidx.test.runner) } iosMain.dependencies { - implementation(libs.sqlDelight.native) +// implementation(libs.sqlDelight.native) +// implementation(libs.sqliteMc.native) implementation(libs.stately.isolate) implementation(libs.stately.iso.collections) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e59e8d2e..bc8d1bd7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,8 @@ gms = "4.4.3" crashlytics = "3.0.6" compose = "1.9.0-rc02" coroutines = "1.10.2" -sqlDelight = "2.1.0" +#sqlDelight = "2.1.0" +sqliteMc = "2.1.0-2.2.3-0" room = "2.8.0" androidxSqlite = "2.6.0" saferoom = "1.3.0" @@ -45,7 +46,6 @@ desugar = "2.1.5" androidSecurityLint = "1.0.3" appdirs = "1.4.0" uiTooling = "1.9.1" -sqliteMc = "2.1.0-2.2.3-0" [libraries] coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "coroutines" } @@ -54,13 +54,19 @@ coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-androi coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing" } coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test" } -sqlDelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqlDelight" } -sqlDelight-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlDelight" } -sqlDelight-native = { module = "app.cash.sqldelight:native-driver", version.ref = "sqlDelight" } -sqlDelight-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlDelight" } -sqlDelight-paging = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqlDelight" } -sqlDelight-coroutinesExt = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" } +#sqlDelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqlDelight" } +#sqlDelight-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlDelight" } +#sqlDelight-native = { module = "app.cash.sqldelight:native-driver", version.ref = "sqlDelight" } +#sqlDelight-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlDelight" } +#sqlDelight-paging = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqlDelight" } +#sqlDelight-coroutinesExt = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" } +sqliteMc-runtime = { module = "io.toxicity.sqlite-mc:runtime", version.ref = "sqliteMc" } +sqliteMc-android = { module = "io.toxicity.sqlite-mc:android-driver", version.ref = "sqliteMc" } +#sqliteMc-native = { module = "io.toxicity.sqlite-mc:native-driver", version.ref = "sqliteMc" } +sqliteMc-jvm = { module = "io.toxicity.sqlite-mc:sqlite-driver", version.ref = "sqliteMc" } +#sqliteMc-paging = { module = "io.toxicity.sqlite-mc:androidx-paging3-extensions", version.ref = "sqliteMc" } +#sqliteMc-coroutinesExt = { module = "io.toxicity.sqlite-mc:coroutines-extensions", version.ref = "sqliteMc" } stately-common = { module = "co.touchlab:stately-common", version.ref = "stately" } #FIXME https://github.com/cashapp/sqldelight/issues/4357 stately-isolate = { module = "co.touchlab:stately-isolate", version.ref = "stately" } @@ -168,7 +174,8 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " compose = { id = "org.jetbrains.compose", version.ref = "compose" } android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } -sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" } +#sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" } +sqliteMc = { id = "io.toxicity.sqlite-mc", version.ref = "sqliteMc" } room = { id = "androidx.room", version.ref = "room" } gms = { id = "com.google.gms.google-services", version.ref = "gms" } crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" }