KOIN - Kotlin simple Dependency Injection Framework for JavaScript/Browser platform
—
Scoped dependency management for controlling instance lifecycle and cleanup within defined boundaries like sessions, requests, or custom application scopes.
Create and manage scoped containers for lifecycle-bound dependencies.
class Scope {
/**
* Get scoped instance from scope
* @param qualifier - Optional qualifier for specific instance
* @param parameters - Optional parameters for instance creation
* @returns Instance of type T from scope
* @throws ClosedScopeException if scope is closed
*/
get<T>(qualifier?: Qualifier, parameters?: () => ParametersHolder): T;
/**
* Get scoped instance or null if not found
* @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?: () => ParametersHolder): T | null;
/**
* Lazy inject from scope - resolved on first access
* @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 from scope
*/
inject<T>(
qualifier?: Qualifier,
mode?: LazyThreadSafetyMode,
parameters?: () => ParametersHolder
): Lazy<T>;
/**
* Link to parent scopes for dependency resolution fallback
* @param scopes - Parent scopes to link to
*/
linkTo(...scopes: Scope[]): void;
/**
* Close scope and cleanup all scoped instances
* Calls onClose callbacks for all managed instances
*/
close(): void;
/**
* Check if scope is closed
* @returns true if scope is closed
*/
closed: boolean;
/**
* Scope identifier
*/
id: string;
/**
* Scope qualifier used for identification
*/
scopeQualifier: Qualifier;
}Usage Examples:
import { startKoin, module, named } from "koin-core";
// Define scoped module
const webModule = module((builder) => {
builder.scope(named("session"), (scopeBuilder) => {
scopeBuilder.scoped(() => new UserSession());
scopeBuilder.scoped(() => new ShoppingCart());
});
});
startKoin((app) => app.modules([webModule]));
// Create and use scope
const koin = GlobalContext.get();
const sessionScope = koin.createScope("user123", named("session"));
try {
// Get scoped instances
const userSession = sessionScope.get(); // UserSession
const cart = sessionScope.get(); // ShoppingCart
// Scoped instances persist within scope
const sameSession = sessionScope.get(); // Same UserSession instance
// Safe retrieval
const optionalService = sessionScope.getOrNull(); // Service | null
} finally {
// Always close scope to cleanup resources
sessionScope.close();
}Create, retrieve, and manage scopes within the Koin container.
class Koin {
/**
* Create new scope with identifier and qualifier
* @param scopeId - Unique scope identifier
* @param qualifier - Scope qualifier defining scope type
* @param source - Optional source object for scope context
* @returns New Scope instance
* @throws ScopeAlreadyCreatedException if scope already exists
*/
createScope(scopeId: string, qualifier: Qualifier, source?: any): Scope;
/**
* Create typed scope with identifier and inferred qualifier
* @param scopeId - Unique scope identifier
* @param source - Optional source object for scope context
* @returns New Scope instance for type T
*/
createScope<T>(scopeId: string, source?: any): Scope;
/**
* Get existing scope by identifier
* @param scopeId - Scope identifier
* @returns Existing Scope instance
* @throws ScopeNotCreatedException if scope doesn't exist
*/
getScope(scopeId: string): Scope;
/**
* Get existing scope or null if not found
* @param scopeId - Scope identifier
* @returns Scope instance or null
*/
getScopeOrNull(scopeId: string): Scope | null;
/**
* Delete scope and cleanup resources
* @param scopeId - Scope identifier to delete
*/
deleteScope(scopeId: string): void;
/**
* Get all active scopes
* @returns Array of all active Scope instances
*/
getAllScopes(): Scope[];
}Usage Examples:
import { startKoin, module, named } from "koin-core";
const appModule = module((builder) => {
builder.scope(named("request"), (scopeBuilder) => {
scopeBuilder.scoped(() => new RequestContext());
scopeBuilder.scoped(() => new DatabaseTransaction());
});
builder.scope(named("session"), (scopeBuilder) => {
scopeBuilder.scoped(() => new UserSession());
});
});
startKoin((app) => app.modules([appModule]));
const koin = GlobalContext.get();
// Create scopes
const requestScope = koin.createScope("req-001", named("request"));
const sessionScope = koin.createScope("session-abc", named("session"), userObject);
// Retrieve existing scopes
const existingRequest = koin.getScope("req-001");
const maybeScope = koin.getScopeOrNull("non-existent"); // null
// Get all active scopes
const allScopes = koin.getAllScopes();
console.log(`Active scopes: ${allScopes.length}`);
// Cleanup
koin.deleteScope("req-001");
sessionScope.close(); // Alternative cleanup methodUse KoinScopeComponent for classes that manage their own scope lifecycle.
interface KoinScopeComponent extends KoinComponent {
/**
* Current scope instance for this component
*/
scope: Scope;
}
// Extension functions for KoinScopeComponent
/**
* Create scope for component with identifier
* @param scopeId - Scope identifier
* @param source - Optional source object
* @returns Created Scope instance
*/
function createScope(
this: KoinScopeComponent,
scopeId: string,
source?: any
): Scope;
/**
* Get component's scope or null if not created
* @returns Scope instance or null
*/
function getScopeOrNull(this: KoinScopeComponent): Scope | null;
/**
* Create lazy scope - scope created on first access
* @returns Lazy<Scope> wrapper
*/
function newScope(this: KoinScopeComponent): Lazy<Scope>;
/**
* Get existing scope or create new one
* @returns Scope instance
*/
function getOrCreateScope(this: KoinScopeComponent): Scope;Usage Examples:
import { KoinScopeComponent, named } from "koin-core";
class UserSessionController extends KoinScopeComponent {
constructor(userId) {
super();
this.userId = userId;
// Create scope for this component
this.scope = this.createScope(`session-${userId}`);
// Get scoped dependencies
this.userSession = this.scope.get(); // UserSession
this.preferences = this.scope.get(); // UserPreferences
}
async login() {
// Use scoped dependencies
await this.userSession.initialize();
await this.preferences.load();
}
async logout() {
// Cleanup scope on logout
this.scope.close();
}
}
class RequestHandler extends KoinScopeComponent {
constructor() {
super();
// Lazy scope creation - created when first accessed
this.lazyScope = this.newScope();
}
async handleRequest(request) {
// Scope created on first access
const scope = this.getOrCreateScope();
const requestContext = scope.get(); // RequestContext
try {
return await requestContext.process(request);
} finally {
// Cleanup after request
scope.close();
}
}
}Create parent-child relationships between scopes for hierarchical dependency resolution.
class Scope {
/**
* Declare instance in scope 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
* @param holdInstance - Whether scope should hold reference
* @returns BeanDefinition for the declared instance
*/
declare<T>(
instance: T,
qualifier?: Qualifier,
secondaryTypes?: any[],
allowOverride?: boolean,
holdInstance?: boolean
): BeanDefinition<T>;
/**
* Get property from scope context
* @param key - Property key
* @param defaultValue - Default value if not found
* @returns Property value
*/
getProperty<T>(key: string, defaultValue?: T): T;
/**
* Get property or null if not found
* @param key - Property key
* @returns Property value or null
*/
getPropertyOrNull<T>(key: string): T | null;
}Usage Examples:
import { startKoin, module, named } from "koin-core";
const hierarchicalModule = module((builder) => {
// Application-level scope
builder.scope(named("application"), (scopeBuilder) => {
scopeBuilder.scoped(() => new ConfigurationService());
scopeBuilder.scoped(() => new Logger());
});
// Session-level scope
builder.scope(named("session"), (scopeBuilder) => {
scopeBuilder.scoped(() => new UserSession());
scopeBuilder.scoped(() => new SecurityContext());
});
// Request-level scope
builder.scope(named("request"), (scopeBuilder) => {
scopeBuilder.scoped(() => new RequestContext());
scopeBuilder.factory(() => new RequestHandler());
});
});
startKoin((app) => app.modules([hierarchicalModule]));
const koin = GlobalContext.get();
// Create scope hierarchy
const appScope = koin.createScope("app", named("application"));
const sessionScope = koin.createScope("session-123", named("session"));
const requestScope = koin.createScope("req-456", named("request"));
// Link scopes for dependency resolution fallback
requestScope.linkTo(sessionScope, appScope);
sessionScope.linkTo(appScope);
// Request scope can resolve from session and app scopes
const requestHandler = requestScope.get(); // RequestHandler (from request scope)
const userSession = requestScope.get(); // UserSession (from session scope)
const config = requestScope.get(); // ConfigurationService (from app scope)
// Declare runtime instances in scope
const runtimeData = { timestamp: Date.now(), requestId: "req-456" };
requestScope.declare(runtimeData, named("request-data"));
// Access declared instance
const data = requestScope.get(named("request-data"));
// Cleanup hierarchy (child scopes first)
requestScope.close();
sessionScope.close();
appScope.close();Handle scope lifecycle events with callbacks for resource management.
interface ScopeCallback {
/**
* Called when scope is created
* @param scope - The created scope
*/
onScopeCreated(scope: Scope): void;
/**
* Called when scope is closed
* @param scope - The closed scope
*/
onScopeClosed(scope: Scope): void;
}
class Koin {
/**
* Register scope callback for lifecycle events
* @param callback - ScopeCallback implementation
*/
registerScopeCallback(callback: ScopeCallback): void;
/**
* Unregister scope callback
* @param callback - ScopeCallback to remove
*/
unregisterScopeCallback(callback: ScopeCallback): void;
}Usage Examples:
import { startKoin, GlobalContext } from "koin-core";
class ScopeMonitor {
onScopeCreated(scope) {
console.log(`Scope created: ${scope.id} (${scope.scopeQualifier.value})`);
}
onScopeClosed(scope) {
console.log(`Scope closed: ${scope.id} (${scope.scopeQualifier.value})`);
}
}
startKoin((app) => app.modules([webModule]));
const koin = GlobalContext.get();
const monitor = new ScopeMonitor();
// Register lifecycle monitoring
koin.registerScopeCallback(monitor);
// Scope operations will trigger callbacks
const scope = koin.createScope("test", named("session")); // Logs: "Scope created..."
scope.close(); // Logs: "Scope closed..."
// Cleanup monitoring
koin.unregisterScopeCallback(monitor);/** Scope identifier type */
type ScopeID = string;
/** Scope callback interface for lifecycle events */
interface ScopeCallback {
onScopeCreated(scope: Scope): void;
onScopeClosed(scope: Scope): void;
}
/** Exception thrown when scope is already created */
class ScopeAlreadyCreatedException extends Error {
constructor(scopeId: string);
}
/** Exception thrown when scope is not created */
class ScopeNotCreatedException extends Error {
constructor(scopeId: string);
}
/** Exception thrown when attempting to use closed scope */
class ClosedScopeException extends Error {
constructor(scopeId: string);
}
/** Exception thrown when scope value is missing */
class MissingScopeValueException extends Error {
constructor(message: string);
}
/** Exception thrown when scope definition is not found */
class NoScopeDefFoundException extends Error {
constructor(message: string);
}Install with Tessl CLI
npx tessl i tessl/maven-io-insert-koin--koin-core-js