CtrlK
BlogDocsLog inGet started
Tessl Logo

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

KOIN - Kotlin simple Dependency Injection Framework for JavaScript/Browser platform

Pending
Overview
Eval results
Files

scoping-lifecycle.mddocs/

Scoping and Lifecycle Management

Scoped dependency management for controlling instance lifecycle and cleanup within defined boundaries like sessions, requests, or custom application scopes.

Capabilities

Scope Management

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();
}

Scope Creation and Management

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 method

Scoped Component Interface

Use 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();
    }
  }
}

Scope Linking and Hierarchies

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();

Scope Callbacks and Lifecycle

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);

Types

/** 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

docs

application-startup.md

context-management.md

dependency-injection.md

error-handling.md

index.md

logging-system.md

module-system.md

qualifiers-parameters.md

scoping-lifecycle.md

tile.json