refactor(frontend, build): update PingViewModel initialization, resolve view model via Koin, and clean yarn dependencies
Injected `PingViewModel` via Koin to align with dependency injection best practices. Suppressed Gradle deprecation warnings and added the `frontend.core.sync` dependency. Cleaned up outdated packages in `yarn.lock`.
This commit is contained in:
@@ -43,8 +43,6 @@ kotlin {
|
||||
implementation(libs.sqldelight.driver.web)
|
||||
|
||||
// NPM deps used by `sqlite.worker.js` (OPFS-backed SQLite WASM worker)
|
||||
implementation(npm("@cashapp/sqldelight-sqljs-worker", "2.2.1"))
|
||||
// Use a published build tag from the official package.
|
||||
implementation(npm("@sqlite.org/sqlite-wasm", "3.51.1-build2"))
|
||||
}
|
||||
|
||||
|
||||
+31
@@ -4,6 +4,14 @@ CREATE TABLE Task (
|
||||
is_completed INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE PingEvent (
|
||||
-- UUIDv7 as String (cursor-friendly and backend-compatible)
|
||||
id TEXT NOT NULL PRIMARY KEY,
|
||||
message TEXT NOT NULL,
|
||||
-- Derived from UUIDv7 timestamp (epoch millis) for sorting/display
|
||||
last_modified INTEGER NOT NULL
|
||||
);
|
||||
|
||||
selectAll:
|
||||
SELECT *
|
||||
FROM Task;
|
||||
@@ -15,3 +23,26 @@ VALUES ?;
|
||||
delete:
|
||||
DELETE FROM Task
|
||||
WHERE id = ?;
|
||||
|
||||
selectPingEventsSince:
|
||||
SELECT *
|
||||
FROM PingEvent
|
||||
WHERE id > ?
|
||||
ORDER BY id;
|
||||
|
||||
selectLatestPingEventId:
|
||||
SELECT id
|
||||
FROM PingEvent
|
||||
ORDER BY id DESC
|
||||
LIMIT 1;
|
||||
|
||||
upsertPingEvents:
|
||||
-- SQLite dialect configured for this project is 3.18 (no UPSERT support).
|
||||
-- Use INSERT OR REPLACE as pragmatic upsert.
|
||||
INSERT OR REPLACE INTO PingEvent(id, message, last_modified)
|
||||
VALUES ?;
|
||||
|
||||
upsertPingEvent:
|
||||
-- Single-row convenience upsert (used by repositories).
|
||||
INSERT OR REPLACE INTO PingEvent(id, message, last_modified)
|
||||
VALUES (?, ?, ?);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
// Targets are configured centrally in the shells/feature modules; here we just provide common code.
|
||||
jvm()
|
||||
js(IR) {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(projects.core.coreDomain)
|
||||
|
||||
// Networking
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.contentNegotiation)
|
||||
implementation(libs.ktor.client.serialization.kotlinx.json)
|
||||
|
||||
// Serialization
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
|
||||
// DI
|
||||
implementation(libs.koin.core)
|
||||
}
|
||||
|
||||
commonTest.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package at.mocode.frontend.core.sync
|
||||
|
||||
import at.mocode.core.sync.Syncable
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
|
||||
/**
|
||||
* Minimaler Repository-Contract für Delta-Sync.
|
||||
*/
|
||||
interface SyncableRepository<T : Syncable> {
|
||||
/**
|
||||
* Cursor für Delta-Sync.
|
||||
*
|
||||
* Konvention: UUIDv7 als String (Backend kann `>` vergleichen) oder ein kompatibler Cursor.
|
||||
*
|
||||
* @return letzter bekannter Cursor lokal oder `null`, wenn noch keine Daten existieren.
|
||||
*/
|
||||
suspend fun getLatestSince(): String?
|
||||
|
||||
/** Insert oder Update (Upsert) der übergebenen Items. */
|
||||
suspend fun upsert(items: List<T>)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generischer Sync-Manager.
|
||||
*
|
||||
* Konvention Backend:
|
||||
* - GET `/api/{entity-plural}/sync?since={timestamp}`
|
||||
* - Response: `List<T>`
|
||||
*/
|
||||
class SyncManager(
|
||||
val ktorClient: HttpClient
|
||||
) {
|
||||
|
||||
suspend inline fun <reified T : Syncable> performSync(
|
||||
repository: SyncableRepository<T>,
|
||||
endpointPath: String
|
||||
) {
|
||||
val since = repository.getLatestSince()
|
||||
|
||||
val remoteItems: List<T> = ktorClient
|
||||
.get(endpointPath) {
|
||||
// `since` optional
|
||||
if (since != null) parameter("since", since)
|
||||
}
|
||||
.body()
|
||||
|
||||
if (remoteItems.isNotEmpty()) {
|
||||
repository.upsert(remoteItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package at.mocode.frontend.core.sync.di
|
||||
|
||||
import at.mocode.frontend.core.sync.SyncManager
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Zentrales Koin-Modul für den Sync-Core.
|
||||
*/
|
||||
val syncModule = module {
|
||||
// Provides a singleton instance of SyncManager, using the globally provided HttpClient.
|
||||
single { SyncManager(get()) }
|
||||
}
|
||||
Reference in New Issue
Block a user