CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-insert-koin--koin-core-wasm-js

Core dependency injection framework for Kotlin Multiplatform projects targeting WebAssembly JavaScript environments

Pending
Overview
Eval results
Files

components.mddocs/

Component Integration

Component interfaces and extension functions for seamless dependency injection integration in your classes.

Capabilities

KoinComponent Interface

Basic interface for classes that need access to dependency injection.

/**
 * Interface for classes that need access to the Koin container
 * Provides access to dependency injection functionality
 */
interface KoinComponent {
    /**
     * Get the Koin container instance
     * @return Koin container for dependency resolution
     */
    fun getKoin(): Koin
}

Usage Examples:

import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.component.get

class UserController : KoinComponent {
    // Lazy injection using delegate
    private val userService: UserService by inject()
    private val emailService: EmailService by inject(named("primary"))
    
    fun registerUser(userData: UserData): User {
        val user = userService.createUser(userData)
        
        // Direct resolution
        val validator = get<UserValidator>()
        validator.validate(user)
        
        emailService.sendWelcomeEmail(user)
        return user
    }
    
    fun handleSpecialCase() {
        // Access Koin container directly
        val koin = getKoin()
        val specialService = koin.getOrNull<SpecialService>()
        
        if (specialService != null) {
            specialService.handleSpecialLogic()
        }
    }
}

KoinComponent Extension Functions

Extension functions that provide convenient dependency injection methods for KoinComponent implementations.

/**
 * Get a dependency instance from the component's Koin container
 * @param qualifier - Optional qualifier to distinguish multiple instances
 * @param parameters - Optional parameters to pass to the factory function
 * @return Instance of the requested type
 */
inline fun <reified T : Any> KoinComponent.get(qualifier: Qualifier? = null, noinline parameters: ParametersDefinition? = null): T

/**
 * Get a lazy dependency from the component's Koin container
 * @param qualifier - Optional qualifier to distinguish multiple instances
 * @param mode - Thread safety mode for the lazy delegate
 * @param parameters - Optional parameters to pass to the factory function
 * @return Lazy delegate that resolves the dependency on first access
 */
inline fun <reified T : Any> KoinComponent.inject(qualifier: Qualifier? = null, mode: LazyThreadSafetyMode = KoinPlatformTools.defaultLazyMode(), noinline parameters: ParametersDefinition? = null): Lazy<T>

Usage Examples:

import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.component.get
import org.koin.core.parameter.parametersOf
import org.koin.core.qualifier.named

class OrderService : KoinComponent {
    // Lazy injection - resolved on first access
    private val paymentService: PaymentService by inject()
    private val inventoryService: InventoryService by inject(named("warehouse"))
    
    // Lazy injection with parameters
    private val shippingCalculator: ShippingCalculator by inject { 
        parametersOf("standard") 
    }
    
    // Note: For optional services, use getKoin().getOrNull() in methods
    
    fun processOrder(order: Order): OrderResult {
        // Direct resolution when needed
        val validator = get<OrderValidator>()
        validator.validateOrder(order)
        
        // Use injected services
        val paymentResult = paymentService.processPayment(order.payment)
        if (!paymentResult.success) {
            return OrderResult.PaymentFailed
        }
        
        // Check inventory
        val available = inventoryService.checkAvailability(order.items)
        if (!available) {
            return OrderResult.OutOfStock
        }
        
        // Calculate shipping
        val shippingCost = shippingCalculator.calculate(order.address, order.items)
        
        // Apply promotions if available
        val promotionService = getKoin().getOrNull<PromotionService>()
        val finalTotal = promotionService?.applyPromotions(order.total) ?: order.total
        
        return OrderResult.Success(finalTotal + shippingCost)
    }
}

KoinScopeComponent Interface

Interface for components that manage their own scope lifecycle.

/**
 * Interface for components that manage their own scope
 * Extends KoinComponent with scope management capabilities
 */
interface KoinScopeComponent : KoinComponent {
    /**
     * The scope associated with this component
     * Components are responsible for managing their scope lifecycle
     */
    val scope: Scope
}

Usage Examples:

import org.koin.core.component.KoinScopeComponent
import org.koin.core.scope.Scope
import org.koin.core.qualifier.named

class WebRequestHandler : KoinScopeComponent {
    // Create scope for this request handler
    override val scope: Scope by lazy {
        getKoin().createScope<RequestScope>("request-${generateId()}")
    }
    
    // Inject from the component's scope
    private val requestContext: RequestContext by scope.inject()
    private val userSession: UserSession by scope.inject()
    private val requestLogger: RequestLogger by scope.inject()
    
    fun handleRequest(request: HttpRequest): HttpResponse {
        requestLogger.logStart(request)
        
        try {
            val user = userSession.getCurrentUser()
            val response = processRequest(request, user)
            requestLogger.logSuccess(response)
            return response
        } catch (e: Exception) {
            requestLogger.logError(e)
            throw e
        }
    }
    
    fun cleanup() {
        // Close scope when component is done
        scope.close()
    }
}

// Usage pattern with try-finally
class RequestProcessor {
    fun processRequest(requestData: RequestData) {
        val handler = WebRequestHandler()
        try {
            val response = handler.handleRequest(requestData.toHttpRequest())
            // Handle response...
        } finally {
            handler.cleanup() // Ensure scope is closed
        }
    }
}

KoinScopeComponent Extension Functions

Extension functions that provide scope management utilities for KoinScopeComponent implementations.

/**
 * Get the scope ID for any object based on its class name
 * @param T - Type of the object
 * @return Generated scope ID string
 */
fun <T : Any> T.getScopeId(): String

/**
 * Get the scope name (type qualifier) for any object
 * @param T - Type of the object
 * @return TypeQualifier based on the object's class
 */
fun <T : Any> T.getScopeName(): TypeQualifier

/**
 * Create a scope for a KoinScopeComponent
 * @param scopeId - Scope identifier (default: generated from object)
 * @param source - Optional source object
 * @param scopeArchetype - Optional scope archetype
 * @return New Scope instance
 */
fun <T : KoinScopeComponent> T.createScope(scopeId: ScopeID = getScopeId(), source: Any? = null, scopeArchetype: TypeQualifier? = null): Scope

/**
 * Create a scope for a KoinScopeComponent with source
 * @param source - Source object for the scope
 * @return New Scope instance
 */
fun <T : KoinScopeComponent> T.createScope(source: Any? = null): Scope

/**
 * Get the scope for a KoinScopeComponent or null if not created
 * @return Existing scope or null
 */
fun <T : KoinScopeComponent> T.getScopeOrNull(): Scope?

/**
 * Create a new scope lazily for a KoinScopeComponent
 * @return Lazy delegate that creates the scope on first access
 */
fun <T : KoinScopeComponent> T.newScope(): Lazy<Scope>

/**
 * Get existing scope or create a new one lazily for a KoinScopeComponent
 * @return Lazy delegate that gets or creates the scope on first access
 */
fun <T : KoinScopeComponent> T.getOrCreateScope(): Lazy<Scope>

Usage Examples:

import org.koin.core.component.KoinScopeComponent
import org.koin.core.component.*

// Different scope creation patterns
class UserSessionManager : KoinScopeComponent {
    // Option 1: Create scope immediately
    override val scope: Scope = createScope(source = this)
    
    private val sessionStore: SessionStore by scope.inject()
    private val userCache: UserCache by scope.inject()
}

class LazySessionManager : KoinScopeComponent {
    // Option 2: Create scope lazily
    override val scope: Scope by newScope()
    
    private val sessionStore: SessionStore by scope.inject()
}

class AdaptiveSessionManager : KoinScopeComponent {
    // Option 3: Get or create scope lazily
    override val scope: Scope by getOrCreateScope()
    
    private val sessionStore: SessionStore by scope.inject()
    
    fun initializeSession(userId: String) {
        // Scope is created here on first access
        scope.declare(UserId(userId))
        
        // Generate scope ID for debugging
        val scopeId = getScopeId()
        val scopeName = getScopeName()
        println("Session scope: $scopeName ($scopeId)")
    }
}

// Usage with explicit scope management
class RequestScopedService : KoinScopeComponent {
    override val scope: Scope by lazy {
        val myScope = createScope("custom-${System.currentTimeMillis()}")
        
        // Register cleanup callback
        myScope.registerCallback(object : ScopeCallback {
            override fun onScopeCreated(qualifier: Qualifier, scope: Scope) {
                println("Scope created: ${scope.id}")
            }
            
            override fun onScopeClosed(qualifier: Qualifier, scope: Scope) {
                println("Scope closed: ${scope.id}")
            }
        })
        
        myScope
    }
    
    private val requestProcessor: RequestProcessor by scope.inject()
    
    fun processAndCleanup() {
        try {
            requestProcessor.process()
        } finally {
            // Check if scope exists before closing
            getScopeOrNull()?.close()
        }
    }
}

Component Patterns

Common patterns for using components effectively.

Singleton Component Pattern:

// Global singleton component
object ApplicationServices : KoinComponent {
    val configService: ConfigService by inject()
    val logService: LogService by inject()
    
    fun initialize() {
        configService.loadConfiguration()
        logService.initialize()
    }
}

// Usage
ApplicationServices.initialize()
val config = ApplicationServices.configService.getConfig("app.name")

Factory Component Pattern:

// Component factory for creating instances
class ComponentFactory : KoinComponent {
    fun createUserProcessor(userId: String): UserProcessor {
        return get<UserProcessor> { parametersOf(userId) }
    }
    
    fun createApiClient(endpoint: String): ApiClient {
        return get<ApiClient> { parametersOf(endpoint) }
    }
}

// Usage
val factory = ComponentFactory()
val processor = factory.createUserProcessor("user-123")
val client = factory.createApiClient("https://api.example.com")

Scoped Component Lifecycle Pattern:

// Base class for scoped components
abstract class ScopedComponent : KoinScopeComponent {
    abstract val scopeQualifier: Qualifier
    
    override val scope: Scope by lazy {
        getKoin().createScope("${scopeQualifier.value}-${generateId()}", scopeQualifier)
    }
    
    open fun initialize() {
        // Subclasses can override for initialization
    }
    
    open fun cleanup() {
        if (!scope.closed) {
            scope.close()
        }
    }
}

// Request-scoped component
class RequestComponent : ScopedComponent() {
    override val scopeQualifier = named("request")
    
    private val requestHandler: RequestHandler by scope.inject()
    private val requestValidator: RequestValidator by scope.inject()
    
    override fun initialize() {
        // Request-specific initialization
        scope.declare(RequestId(generateRequestId()))
    }
}

// Usage with automatic cleanup
inline fun <T> withRequestComponent(block: (RequestComponent) -> T): T {
    val component = RequestComponent()
    return try {
        component.initialize()
        block(component)
    } finally {
        component.cleanup()
    }
}

// Usage
withRequestComponent { component ->
    val result = component.requestHandler.handle(request)
    // Component is automatically cleaned up
    result
}

Type Definitions

/**
 * Base interface for dependency injection components
 */
interface KoinComponent {
    fun getKoin(): Koin
}

/**
 * Interface for components with scope management
 */
interface KoinScopeComponent : KoinComponent {
    val scope: Scope
}

/**
 * Generate a unique ID for scopes and components
 * @return Generated unique identifier string
 */
fun generateId(): String

/**
 * Type alias for type-based qualifiers
 */
class TypeQualifier : Qualifier {
    val type: KClass<*>
}

Install with Tessl CLI

npx tessl i tessl/maven-io-insert-koin--koin-core-wasm-js

docs

application.md

components.md

dependency-injection.md

global-context.md

index.md

modules.md

scopes.md

tile.json