From 37d7121bc11ba8a271b8fc37e897bab354f9ff43 Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Sat, 14 Dec 2024 22:40:40 +0200 Subject: [PATCH 1/5] Fix deprecation --- di/build.gradle.kts | 78 ++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/di/build.gradle.kts b/di/build.gradle.kts index ee3b08d..467dc2b 100644 --- a/di/build.gradle.kts +++ b/di/build.gradle.kts @@ -1,51 +1,55 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl plugins { - alias(libs.plugins.kotlinMultiplatform) - alias(libs.plugins.androidLibrary) - alias(libs.plugins.publish) + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidLibrary) + alias(libs.plugins.publish) } kotlin { - jvm() - androidTarget { - publishLibraryVariants("release") - @OptIn(ExperimentalKotlinGradlePluginApi::class) - compilerOptions { - jvmTarget.set(JvmTarget.JVM_1_8) - } + jvm() + androidTarget { + publishLibraryVariants("release") + @OptIn(ExperimentalKotlinGradlePluginApi::class) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) } - iosX64() - iosArm64() - iosSimulatorArm64() - linuxX64() - js(IR) { - browser() - nodejs() - } - @OptIn(ExperimentalWasmDsl::class) wasmJs() + } + iosX64() + iosArm64() + iosSimulatorArm64() + linuxX64() + js(IR) { + browser() + nodejs() + } + @OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) + wasmJs { + browser() + nodejs() + d8() + } - sourceSets { - val commonMain by getting { - dependencies { - //put your multiplatform dependencies here - } - } - val commonTest by getting { - dependencies { - implementation(libs.kotlin.test) - implementation(libs.bundles.test) - } - } + sourceSets { + val commonMain by getting { + dependencies { + //put your multiplatform dependencies here + } + } + val commonTest by getting { + dependencies { + implementation(libs.kotlin.test) + implementation(libs.bundles.test) + } } + } } android { - namespace = "com.ivy_apps.di" - compileSdk = libs.versions.android.compileSdk.get().toInt() - defaultConfig { - minSdk = libs.versions.android.minSdk.get().toInt() - } + namespace = "com.ivy_apps.di" + compileSdk = libs.versions.android.compileSdk.get().toInt() + defaultConfig { + minSdk = libs.versions.android.minSdk.get().toInt() + } } From d566c02131e1331adaea5e4c2b732dc4114abf38 Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Sat, 14 Dec 2024 22:46:35 +0200 Subject: [PATCH 2/5] Improve KDoc --- di/src/commonMain/kotlin/ivy/di/DiContainer.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/di/src/commonMain/kotlin/ivy/di/DiContainer.kt b/di/src/commonMain/kotlin/ivy/di/DiContainer.kt index ac49315..a96232e 100644 --- a/di/src/commonMain/kotlin/ivy/di/DiContainer.kt +++ b/di/src/commonMain/kotlin/ivy/di/DiContainer.kt @@ -6,7 +6,16 @@ import kotlin.reflect.KClass typealias Factory = () -> Any +/** + * Built-in [Di.Scope] for registering dependencies for the lifetime of the application. + * __Note:__ you need to manually manage the lifecycle by clearing when no longer needed + * via [Di.clear]. + */ val AppScope = Di.newScope("app") + +/** + * Same like [AppScope] but for the lifetime of a feature. + */ val FeatureScope = Di.newScope("feature") object Di { @@ -30,12 +39,14 @@ object Di { } /** - * Scope used to register dependencies for the entire lifetime of the application. + * Scope used to register dependencies in [AppScope], + * intended for the entire lifetime of the application. */ fun appScope(block: Scope.() -> Unit) = AppScope.block() /** - * Scope used to register dependencies for a feature. + * Scope used to register dependencies in [FeatureScope] + * intended for the lifetime of the feature for a feature. */ fun featureScope(block: Scope.() -> Unit) = FeatureScope.block() @@ -47,7 +58,8 @@ object Di { fun newScope(name: String): Scope = Scope(name).also(scopes::add) /** - * Utility function for registering dependencies in a specific scope. + * Utility function for registering dependencies in a specific [scope]. + * @param scope the [Di.Scope] in which the dependencies will be registered */ fun inScope(scope: Scope, block: Scope.() -> Unit) = scope.block() From 0c51371f8fad8416709fe8210d76a4eb39e9a18b Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Sat, 14 Dec 2024 22:55:45 +0200 Subject: [PATCH 3/5] Improve KDoc --- .../kotlin/ivy/di/autowire/Autowire.kt | 21 +++++++++++-------- .../ivy/di/autowire/AutowireSingleton.kt | 19 +---------------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/di/src/commonMain/kotlin/ivy/di/autowire/Autowire.kt b/di/src/commonMain/kotlin/ivy/di/autowire/Autowire.kt index 5e43496..6d02f34 100644 --- a/di/src/commonMain/kotlin/ivy/di/autowire/Autowire.kt +++ b/di/src/commonMain/kotlin/ivy/di/autowire/Autowire.kt @@ -11,18 +11,21 @@ import kotlin.jvm.JvmName * Make sure to **import [R] before** calling `autoWire(::R)`, * otherwise your IDE might not recognize the function. * - * @param constructor A function reference to the constructor of the dependency like `::R`. - * [R] must be imported before calling this function. - * + * The affinity of the dependencies of [R] will be set to the receiver scope. * ``` - * class Repository(val a: A, val b: B, val c: C) + *class Repository(val a: A, val b: B) * - * Di.appScope { - * autoWire(::Repository) - * // equivalent to: - * // register { Repository(Di.get(), Di.get(), Di.get()) } - * } + *Di.appScope { + * autoWire(::Repository) + * // equivalent to: + * // register { Repository(Di.get(affinity = AppScope), Di.get(affinity = AppScope)) } + *} * ``` + * + * @receiver the [Scope] in which to wire the [R] dependency. + * [R]'s dependencies will have affinity for the receiver [Scope]. + * @param constructor A function reference to the constructor of the dependency like `::R`. + * [R] must be imported before calling this function. */ inline fun Scope.autoWire( crossinline constructor: () -> R, diff --git a/di/src/commonMain/kotlin/ivy/di/autowire/AutowireSingleton.kt b/di/src/commonMain/kotlin/ivy/di/autowire/AutowireSingleton.kt index 5c9a812..fb63808 100644 --- a/di/src/commonMain/kotlin/ivy/di/autowire/AutowireSingleton.kt +++ b/di/src/commonMain/kotlin/ivy/di/autowire/AutowireSingleton.kt @@ -5,24 +5,7 @@ import ivy.di.Di.singleton import kotlin.jvm.JvmName /** - * Automatically registers a singleton factory for a dependency [R] with the given constructor. - * [ivy.di.Di.get] will be called for each constructor parameter of [R]. - * - * Make sure to **import [R] before** calling `autoWireSingleton(::R)`, - * otherwise your IDE might not recognize the function. - * - * @param constructor A function reference to the constructor of the dependency like `::R`. - * [R] must be imported before calling this function. - * - * ``` - * class Repository(val a: A, val b: B, val c: C) - * - * Di.appScope { - * autoWireSingleton(::Repository) - * // equivalent to: - * // singleton { Repository(Di.get(), Di.get(), Di.get()) } - * } - * ``` + * Same as [autoWire] but for [singleton]s. */ inline fun Scope.autoWireSingleton( crossinline constructor: () -> R, From 902f865ee3f832cd46a2bf7d1751e5be567b4f5e Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Sat, 14 Dec 2024 22:57:35 +0200 Subject: [PATCH 4/5] Improve KDoc --- .../commonMain/kotlin/ivy/di/DiContainer.kt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/di/src/commonMain/kotlin/ivy/di/DiContainer.kt b/di/src/commonMain/kotlin/ivy/di/DiContainer.kt index a96232e..9ca67e3 100644 --- a/di/src/commonMain/kotlin/ivy/di/DiContainer.kt +++ b/di/src/commonMain/kotlin/ivy/di/DiContainer.kt @@ -256,6 +256,37 @@ object Di { * Di.get(affinity = FeatureScope) // "world" * Di.get() // not deterministic * ``` + * + * An example for managing lifecycle using DI scopes: + * + * ```kotlin + * data class UserInfo(val id: String, val name: String) + * + * val UserScope = Di.newScope("user") + * fun Di.userScope(block: Di.Scope.() -> Unit) = Di.inScope(UserScope, block) // helper function (optional) + * + * suspend fun login() { + * val userInfo = loginInternally() // UserInfo("1", "John") + * Di.userScope { + * // Register dependencies for the lifecycle of a user + * singleton { userInfo } + * } + * } + * + * // Note: This function must be called only for logged-in users, + * // otherwise Di.get() will throw an exception. + * suspend fun dashboard() { + * // Use user related dependencies + * val userInfo = Di.get() + * println("Hello, ${userInfo.name}") // "Hello, John" + * } + * + * suspend fun logout() { + * logoutInternally() + * // Frees all dependencies in UserScope + * Di.clear(UserScope) // UserInfo("1", "John") gets cleared + * } + * ``` */ @JvmInline value class Scope internal constructor(val value: String) From f36343842132e8d4c84cf7b316b6f9d27fba96e4 Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Sat, 14 Dec 2024 23:07:23 +0200 Subject: [PATCH 5/5] Add disclaimer to the README --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index fd01b57..0b6c7ef 100644 --- a/README.md +++ b/README.md @@ -401,3 +401,13 @@ dependencies on the main thread. The library will be maintained as long as Ivy Apps Ltd has an interest in using it. Given that Ivy DI currently has no community, the project may be abandoned in the future. + +> **Disclaimer** +> +> _Ivy DI is provided "as is" under the [Apache 2.0 License](LICENSE), +without warranties of any kind, including but not limited to +fitness for a particular purpose or security. +Use it at your own risk. The authors are not liable for +any issues, defects, security vulnerabilities, +or damages arising from its use. +Maintenance, updates, and support are not guaranteed._ \ No newline at end of file