KOIN - Kotlin simple Dependency Injection Framework for JavaScript/Browser platform
—
Core dependency injection functionality for retrieving instances, lazy injection, parameter passing, and component-based dependency access.
Get instances from the Koin container with type safety and parameter injection.
class Koin {
/**
* Get instance of type T from the container
* @param qualifier - Optional qualifier for specific instance
* @param parameters - Optional parameters for instance creation
* @returns Instance of type T
* @throws NoDefinitionFoundException if definition not found
*/
get<T>(qualifier?: Qualifier, parameters?: ParametersDefinition): T;
get<T>(clazz: any, qualifier?: Qualifier, parameters?: ParametersDefinition): T;
/**
* Get instance or null if not found - safe alternative to get()
* @param qualifier - Optional qualifier for specific instance
* @param parameters - Optional parameters for instance creation
* @returns Instance of type T or null if not found
*/
getOrNull<T>(qualifier?: Qualifier, parameters?: ParametersDefinition): T | null;
getOrNull<T>(clazz: any, qualifier?: Qualifier, parameters?: ParametersDefinition): T | null;
/**
* Lazy injection - resolved on first access
* @param qualifier - Optional qualifier for specific instance
* @param mode - Thread safety mode for lazy initialization (default: SYNCHRONIZED)
* @param parameters - Optional parameters for instance creation
* @returns Lazy<T> wrapper that resolves on first access
*/
inject<T>(
qualifier?: Qualifier,
mode?: LazyThreadSafetyMode,
parameters?: ParametersDefinition
): Lazy<T>;
/**
* Lazy injection that can return null if not found
* @param qualifier - Optional qualifier for specific instance
* @param mode - Thread safety mode for lazy initialization (default: SYNCHRONIZED)
* @param parameters - Optional parameters for instance creation
* @returns Lazy<T | null> wrapper that resolves on first access
*/
injectOrNull<T>(
qualifier?: Qualifier,
mode?: LazyThreadSafetyMode,
parameters?: ParametersDefinition
): Lazy<T | null>;
/**
* Get all instances of type T from the container
* @returns Array of all instances matching type T
*/
getAll<T>(): T[];
/**
* Declare existing instance in container for injection
* @param instance - Instance to declare
* @param qualifier - Optional qualifier for identification
* @param secondaryTypes - Additional types to bind
* @param allowOverride - Whether to allow overriding existing definition
*/
declare<T>(
instance: T,
qualifier?: Qualifier,
secondaryTypes?: any[],
allowOverride?: boolean
): void;
}Usage Examples:
import { startKoin, module } from "koin-core";
// Setup
const appModule = module((builder) => {
builder.single(() => new DatabaseService("localhost:5432"));
builder.factory(() => new ApiClient());
builder.single("cache", () => new CacheService());
});
startKoin((app) => app.modules([appModule]));
// Get Koin instance
const koin = GlobalContext.get();
// Basic instance retrieval
const database = koin.get(); // DatabaseService
const apiClient = koin.get(); // ApiClient (new instance each time)
// Qualified instance retrieval
const cache = koin.get("cache"); // CacheService
// Safe retrieval
const optionalService = koin.getOrNull(); // Service | null
// With parameters
const userService = koin.get(null, () => parametersOf("user123", true));
// Get all instances of a type
const allHandlers = koin.getAll(); // MessageHandler[]
// Declare runtime instance
const runtimeService = new RuntimeService();
koin.declare(runtimeService, "runtime");Use the KoinComponent interface to add dependency injection capabilities to your classes.
interface KoinComponent {
/**
* Get the Koin container instance
* @returns Koin container for dependency resolution
*/
getKoin(): Koin;
}
// Extension functions for KoinComponent
/**
* Get dependency instance from component
* @param qualifier - Optional qualifier for specific instance
* @param parameters - Optional parameters for instance creation
* @returns Instance of type T
*/
function get<T>(
this: KoinComponent,
qualifier?: Qualifier,
parameters?: () => ParametersHolder
): T;
/**
* Lazy dependency injection for component
* @param qualifier - Optional qualifier for specific instance
* @param mode - Thread safety mode for lazy initialization
* @param parameters - Optional parameters for instance creation
* @returns Lazy<T> wrapper that resolves on first access
*/
function inject<T>(
this: KoinComponent,
qualifier?: Qualifier,
mode?: LazyThreadSafetyMode,
parameters?: () => ParametersHolder
): Lazy<T>;Usage Examples:
import { KoinComponent } from "koin-core";
class UserController extends KoinComponent {
constructor() {
super();
// Direct injection
this.userService = this.get(); // UserService
this.logger = this.get("console"); // ConsoleLogger
// Lazy injection - resolved on first access
this.cacheLazy = this.inject(); // Lazy<CacheService>
this.apiClientLazy = this.inject("external"); // Lazy<ExternalApiClient>
}
async getUser(id) {
// Access lazy dependencies
const cache = this.cacheLazy.value;
const apiClient = this.apiClientLazy.value;
// Use injected dependencies
this.logger.info(`Getting user ${id}`);
return await this.userService.findById(id);
}
}
// Alternative implementation using composition
class ProductService {
constructor() {
this.koinComponent = new KoinComponent();
this.database = this.koinComponent.get(); // DatabaseService
this.validator = this.koinComponent.get("product"); // ProductValidator
}
}Inject configuration properties and runtime values.
class Koin {
/**
* Get property value by key
* @param key - Property key
* @param defaultValue - Default value if property not found
* @returns Property value of type T
*/
getProperty<T>(key: string, defaultValue?: T): T;
/**
* Get property value or null if not found
* @param key - Property key
* @returns Property value or null
*/
getPropertyOrNull<T>(key: string): T | null;
/**
* Set property value
* @param key - Property key
* @param value - Property value
*/
setProperty(key: string, value: any): void;
/**
* Delete property by key
* @param key - Property key
*/
deleteProperty(key: string): void;
}
// Extension functions for KoinComponent
/**
* Get property from component context
* @param key - Property key
* @param defaultValue - Default value if property not found
* @returns Property value
*/
function getProperty<T>(
this: KoinComponent,
key: string,
defaultValue?: T
): T;Usage Examples:
import { startKoin, module, KoinComponent } from "koin-core";
// Setup with properties
startKoin((app) => {
app.modules([appModule]);
app.properties(new Map([
["database.url", "mongodb://localhost:27017"],
["api.timeout", 5000],
["debug.enabled", true]
]));
});
class DatabaseService extends KoinComponent {
constructor() {
super();
// Inject properties with defaults
this.url = this.getProperty("database.url", "mongodb://localhost:27017");
this.timeout = this.getProperty("api.timeout", 3000);
this.debugEnabled = this.getProperty("debug.enabled", false);
}
}
// Direct property access
const koin = GlobalContext.get();
const apiUrl = koin.getProperty("api.url", "https://api.default.com");
const debugMode = koin.getPropertyOrNull("debug.mode"); // boolean | null
// Runtime property updates
koin.setProperty("cache.ttl", 300);
koin.deleteProperty("temp.flag");Pass parameters during dependency resolution for dynamic instance creation.
/**
* Create parameters holder for injection
* @param parameters - Parameter values in order
* @returns ParametersHolder with indexed access
*/
function parametersOf(...parameters: any[]): ParametersHolder;
/**
* Create indexed parameter array
* @param parameters - Parameter values
* @returns ParametersHolder with array-like access
*/
function parameterArrayOf(...parameters: any[]): ParametersHolder;
/**
* Create parameter set for type-based access
* @param parameters - Parameter values
* @returns ParametersHolder with type-based access
*/
function parameterSetOf(...parameters: any[]): ParametersHolder;
/**
* Create empty parameters holder
* @returns Empty ParametersHolder
*/
function emptyParametersHolder(): ParametersHolder;
class ParametersHolder {
/**
* Get parameter by index and expected type
* @param index - Parameter index
* @param clazz - Expected parameter type
* @returns Parameter value of type T
*/
elementAt<T>(index: number, clazz?: new (...args: any[]) => T): T;
/**
* Get parameter by type (first matching type)
* @returns Parameter value of type T
*/
get<T>(): T;
/**
* Check if parameters are empty
* @returns true if no parameters
*/
isEmpty(): boolean;
/**
* Check if parameters exist
* @returns true if parameters exist
*/
isNotEmpty(): boolean;
/**
* Get parameter count
* @returns Number of parameters
*/
size(): number;
/**
* Destructuring support - get first parameter
* @returns First parameter
*/
component1<T>(): T;
/**
* Destructuring support - get second parameter
* @returns Second parameter
*/
component2<T>(): T;
/**
* Destructuring support - get third parameter
* @returns Third parameter
*/
component3<T>(): T;
/**
* Destructuring support - get fourth parameter
* @returns Fourth parameter
*/
component4<T>(): T;
/**
* Destructuring support - get fifth parameter
* @returns Fifth parameter
*/
component5<T>(): T;
}Usage Examples:
import { module, parametersOf, KoinComponent } from "koin-core";
// Module with parameter-accepting definitions
const userModule = module((builder) => {
builder.factory((scope, params) => {
const userId = params.get(); // string
const includeProfile = params.elementAt(1); // boolean
return new UserService(userId, includeProfile);
});
builder.single((scope, params) => {
const [host, port, database] = params.component1(), params.component2(), params.component3();
return new DatabaseConnection(host, port, database);
});
});
class UserController extends KoinComponent {
async getUser(userId, includeProfile = false) {
// Pass parameters during injection
const userService = this.get(null, () =>
parametersOf(userId, includeProfile)
);
return await userService.getUser();
}
async connectToDatabase() {
// Multiple parameters
const dbConnection = this.get(null, () =>
parametersOf("localhost", 5432, "myapp")
);
return dbConnection.connect();
}
}
// Different parameter creation methods
const indexedParams = parametersOf("value1", 42, true);
const arrayParams = parameterArrayOf("item1", "item2", "item3");
const setParams = parameterSetOf(new Date(), "config", 100);
const emptyParams = emptyParametersHolder();Defer dependency resolution until first access for performance optimization.
interface Lazy<T> {
/**
* Get the lazily resolved value - resolved on first access
*/
value: T;
}
/**
* Thread safety modes for lazy initialization
*/
enum LazyThreadSafetyMode {
/** Thread-safe lazy initialization */
SYNCHRONIZED = "SYNCHRONIZED",
/** Not thread-safe but faster */
NONE = "NONE",
/** Thread-safe with publication safety */
PUBLICATION = "PUBLICATION"
}Usage Examples:
import { KoinComponent, LazyThreadSafetyMode } from "koin-core";
class ApplicationService extends KoinComponent {
constructor() {
super();
// Lazy dependencies - resolved on first access
this.expensiveService = this.inject(); // Lazy<ExpensiveService>
this.cacheService = this.inject("redis"); // Lazy<RedisCache>
// Thread-safe lazy with specific mode
this.sharedResource = this.inject(
"shared",
LazyThreadSafetyMode.SYNCHRONIZED
); // Lazy<SharedResource>
}
async processData(data) {
// Services are created only when first accessed
const expensive = this.expensiveService.value; // Created here if not already
const cache = this.cacheService.value; // Created here if not already
// Subsequent access uses cached instance
const cachedResult = this.cacheService.value.get("result");
return await expensive.process(data);
}
}
// Manual lazy injection
const koin = GlobalContext.get();
const lazyLogger = koin.inject("file"); // Lazy<FileLogger>
// Access when needed
function logMessage(message) {
const logger = lazyLogger.value; // Created on first access
logger.log(message);
}/** Function type for parameter definitions */
type ParametersDefinition = () => ParametersHolder;
/** Thread safety modes for lazy initialization */
enum LazyThreadSafetyMode {
SYNCHRONIZED = "SYNCHRONIZED",
NONE = "NONE",
PUBLICATION = "PUBLICATION"
}
/** Lazy wrapper interface */
interface Lazy<T> {
value: T;
}
/** Exception thrown when definition is not found */
class NoDefinitionFoundException extends Error {
constructor(message: string);
}
/** Exception thrown when instance creation fails */
class InstanceCreationException extends Error {
constructor(message: string, cause?: Error);
}
/** Exception thrown when required parameter is not found */
class NoParameterFoundException extends Error {
constructor(message: string);
}Install with Tessl CLI
npx tessl i tessl/maven-io-insert-koin--koin-core-js