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

module-system.mddocs/

Module System and Dependency Definitions

Module definition DSL for organizing and declaring dependencies with singletons, factories, scoped instances, and constructor-based definitions.

Capabilities

Module Creation

Define modules with dependency definitions using the fluent DSL.

/**
 * Define a module with dependency definitions
 * @param createdAtStart - Whether to create instances immediately on startup (default: false)
 * @param moduleDeclaration - Module configuration function
 * @returns Module instance
 */
function module(
  createdAtStart?: boolean,
  moduleDeclaration: ModuleDeclaration
): Module;

/**
 * Define a module with only the declaration function
 * @param moduleDeclaration - Module configuration function
 * @returns Module instance
 */
function module(moduleDeclaration: ModuleDeclaration): Module;

/**
 * Create a Koin configuration
 * @param declaration - Application configuration function
 * @returns KoinConfiguration instance
 */
function koinConfiguration(declaration: KoinAppDeclaration): KoinConfiguration;

Usage Examples:

import { module } from "koin-core";

// Basic module definition
const appModule = module((module) => {
  module.single(null, false, () => new DatabaseService());
  module.factory(null, () => new ApiClient());
});

// Module with eager creation
const eagerModule = module(true, (module) => {
  module.single(null, true, () => new ConfigurationService());
});

Dependency Definitions

Define different types of dependencies within modules.

class Module {
  /** Module unique identifier */
  readonly id: string;
  /** Whether module is loaded */
  readonly isLoaded: boolean;

  /**
   * Define singleton instance - created once and reused
   * @param qualifier - Optional qualifier for instance identification
   * @param createdAtStart - Whether to create immediately (default: false)
   * @param definition - Function that creates the instance
   * @returns KoinDefinition for additional configuration
   */
  single<T>(
    qualifier?: Qualifier,
    createdAtStart?: boolean,
    definition: Definition<T>
  ): KoinDefinition<T>;

  /**
   * Define factory instance - new instance every request
   * @param qualifier - Optional qualifier for instance identification
   * @param definition - Function that creates the instance
   * @returns KoinDefinition for additional configuration
   */
  factory<T>(qualifier?: Qualifier, definition: Definition<T>): KoinDefinition<T>;
  
  /**
   * Define scoped instances within named scope
   * @param qualifier - Scope qualifier
   * @param scopeSet - Scope configuration function
   */
  scope(qualifier: Qualifier, scopeSet: (scopeDSL: ScopeDSL) => void): void;
  scope<T>(scopeSet: (scopeDSL: ScopeDSL) => void): void;
  
  /**
   * Include other modules
   * @param modules - Modules to include
   */
  includes(...modules: Module[]): void;
  includes(modules: Module[]): void;
  
  /**
   * Module composition operators
   */
  plus(module: Module): Module[];
  plus(modules: Module[]): Module[];
}

Usage Examples:

import { module, named } from "koin-core";

const appModule = module((module) => {
  // Singleton - created once, reused
  module.single(null, false, () => new DatabaseConnection("localhost:5432"));
  
  // Qualified singleton
  module.single(named("primary"), false, () => new DatabaseConnection("primary-db:5432"));
  
  // Factory - new instance each time
  module.factory(null, () => new HttpRequest());
  
  // Qualified factory
  module.factory(named("api"), () => new ApiClient("https://api.example.com"));
  
  // Eager singleton - created at startup
  module.single(null, true, () => new ConfigurationLoader());
});

Constructor-Based Definitions

Enhanced DSL functions for constructor-based dependency definitions with automatic parameter resolution.

/**
 * Constructor-based singleton definition with 0 parameters
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function singleOf<T>(constructor: () => T): BeanDefinition<T>;

/**
 * Constructor-based singleton definition with 1 parameter
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function singleOf<T, P1>(constructor: (p1: P1) => T): BeanDefinition<T>;

/**
 * Constructor-based singleton definition with 2 parameters
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function singleOf<T, P1, P2>(constructor: (p1: P1, p2: P2) => T): BeanDefinition<T>;

// Additional variants for up to 22 parameters...

/**
 * Constructor-based factory definition with 0 parameters
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function factoryOf<T>(constructor: () => T): BeanDefinition<T>;

/**
 * Constructor-based factory definition with 1 parameter
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function factoryOf<T, P1>(constructor: (p1: P1) => T): BeanDefinition<T>;

// Additional factoryOf variants for up to 22 parameters...

/**
 * Constructor-based scoped definition with 0 parameters
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration
 */
function scopedOf<T>(constructor: () => T): BeanDefinition<T>;

/**
 * Constructor-based scoped definition with 1 parameter
 * @param constructor - Constructor function
 * @returns BeanDefinition for additional configuration  
 */
function scopedOf<T, P1>(constructor: (p1: P1) => T): BeanDefinition<T>;

// Additional scopedOf variants for up to 22 parameters...

Usage Examples:

import { module, singleOf, factoryOf } from "koin-core";

class DatabaseService {
  constructor(connectionString) {
    this.connectionString = connectionString;
  }
}

class ApiClient {
  constructor(baseUrl, timeout) {
    this.baseUrl = baseUrl;
    this.timeout = timeout;
  }
}

const appModule = module((builder) => {
  // Constructor-based definitions automatically resolve parameters
  builder.singleOf(DatabaseService); // Auto-resolves constructor parameters
  builder.factoryOf(ApiClient);       // Auto-resolves constructor parameters
  
  // Dependencies for constructors
  builder.single(() => "mongodb://localhost:27017"); // For DatabaseService
  builder.single(() => "https://api.example.com");   // For ApiClient baseUrl
  builder.single(() => 5000);                        // For ApiClient timeout
});

Scope Definitions

Define scoped dependencies that live within specific lifecycle boundaries.

class Module {
  /**
   * Define scoped instances within named scope
   * @param qualifier - Scope identifier
   * @param scopeSet - Scope configuration function
   * @returns Module for chaining
   */
  scope(qualifier: Qualifier, scopeSet: (builder: ScopeBuilder) => void): Module;
}

class ScopeBuilder {
  /**
   * Define scoped instance within scope
   * @param definition - Function that creates the instance
   * @returns BeanDefinition for additional configuration
   */
  scoped<T>(definition: (scope: Scope, parameters: ParametersHolder) => T): BeanDefinition<T>;

  /**
   * Define qualified scoped instance
   * @param qualifier - Qualifier for instance identification
   * @param definition - Function that creates the instance
   * @returns BeanDefinition for additional configuration
   */
  scoped<T>(
    qualifier: Qualifier,
    definition: (scope: Scope, parameters: ParametersHolder) => T
  ): BeanDefinition<T>;

  /**
   * Define factory instance within scope
   * @param definition - Function that creates the instance
   * @returns BeanDefinition for additional configuration
   */
  factory<T>(definition: (scope: Scope, parameters: ParametersHolder) => T): BeanDefinition<T>;

  /**
   * Define qualified factory instance within scope
   * @param qualifier - Qualifier for instance identification  
   * @param definition - Function that creates the instance
   * @returns BeanDefinition for additional configuration
   */
  factory<T>(
    qualifier: Qualifier,
    definition: (scope: Scope, parameters: ParametersHolder) => T
  ): BeanDefinition<T>;
}

Usage Examples:

import { module, named } from "koin-core";

const webModule = module((builder) => {
  // Define a session scope
  builder.scope(named("session"), (scopeBuilder) => {
    // User session - lives for duration of session scope
    scopeBuilder.scoped(() => new UserSession());
    
    // Shopping cart - lives for duration of session scope  
    scopeBuilder.scoped(() => new ShoppingCart());
    
    // HTTP request factory - new instance per request within session
    scopeBuilder.factory(() => new HttpRequest());
  });
  
  // Define a request scope
  builder.scope(named("request"), (scopeBuilder) => {
    scopeBuilder.scoped(() => new RequestContext());
    scopeBuilder.scoped(named("api"), () => new ApiRequestHandler());
  });
});

Module Composition

Combine and organize modules for complex applications.

class Module {
  /**
   * Include other modules in this module
   * @param modules - Modules to include
   * @returns Module for chaining
   */
  includes(...modules: Module[]): Module;

  /**
   * Combine modules using plus operator
   * @param module - Module to combine
   * @returns New combined module
   */
  plus(module: Module): Module;

  /**
   * Combine with multiple modules
   * @param modules - Modules to combine
   * @returns New combined module
   */
  plus(modules: Module[]): Module;
}

Usage Examples:

import { module } from "koin-core";

const coreModule = module((builder) => {
  builder.single(() => new Logger());
  builder.single(() => new ConfigService());
});

const databaseModule = module((builder) => {
  builder.single(() => new DatabaseConnection());
  builder.factory(() => new Repository());
});

const apiModule = module((builder) => {
  builder.factory(() => new ApiClient());
  builder.single(() => new AuthService());
});

// Combine modules using includes
const appModule = module((builder) => {
  builder.includes(coreModule, databaseModule, apiModule);
  builder.single(() => new AppService());
});

// Combine modules using plus operator
const combinedModule = coreModule.plus(databaseModule).plus(apiModule);

// Alternative combination syntax
const allModules = coreModule.plus([databaseModule, apiModule]);

Bean Definition Configuration

Configure bean definitions with type binding and lifecycle callbacks.

interface BeanDefinition<T> {
  /**
   * Bind additional compatible types for injection
   * @param clazz - Class or interface to bind
   * @returns BeanDefinition for chaining
   */
  bind<S>(clazz: new (...args: any[]) => S): BeanDefinition<T>;

  /**
   * Bind additional compatible type using generics
   * @returns BeanDefinition for chaining
   */
  bind<S>(): BeanDefinition<T>;

  /**
   * Bind multiple compatible types
   * @param classes - Array of classes to bind
   * @returns BeanDefinition for chaining
   */
  binds(classes: (new (...args: any[]) => any)[]): BeanDefinition<T>;

  /**
   * Add cleanup callback when instance is closed
   * @param callback - Cleanup function
   * @returns BeanDefinition for chaining
   */
  onClose(callback: (instance: T) => void): BeanDefinition<T>;
}

Usage Examples:

import { module } from "koin-core";

// Interfaces for binding
class DatabaseService {}
class IDataService {}
class ILoggable {}

const appModule = module((builder) => {
  // Bind additional types for polymorphic injection
  builder
    .single(() => new DatabaseService())
    .bind(IDataService)
    .bind(ILoggable)
    .onClose((instance) => {
      console.log("Closing database service");
      instance.close();
    });
    
  // Bind multiple types at once
  builder
    .factory(() => new HttpClient())
    .binds([IHttpClient, IRequestHandler])
    .onClose((instance) => instance.cleanup());
});

Types

/** Function type for module declarations */
type ModuleDeclaration = (builder: ModuleBuilder) => void;

/** Function type for dependency definitions */
type Definition<T> = (scope: Scope, parameters: ParametersHolder) => T;

/** Function type for cleanup callbacks */
type OnCloseCallback<T> = (instance: T) => void;

/** Module builder interface for DSL */
interface ModuleBuilder {
  single<T>(definition: Definition<T>): BeanDefinition<T>;
  single<T>(qualifier: Qualifier, definition: Definition<T>): BeanDefinition<T>;
  factory<T>(definition: Definition<T>): BeanDefinition<T>;
  factory<T>(qualifier: Qualifier, definition: Definition<T>): BeanDefinition<T>;
  scope(qualifier: Qualifier, scopeSet: (builder: ScopeBuilder) => void): Module;
}

/** Scope builder interface for scoped definitions */
interface ScopeBuilder {
  scoped<T>(definition: Definition<T>): BeanDefinition<T>;
  scoped<T>(qualifier: Qualifier, definition: Definition<T>): BeanDefinition<T>;
  factory<T>(definition: Definition<T>): BeanDefinition<T>;
  factory<T>(qualifier: Qualifier, definition: Definition<T>): BeanDefinition<T>;
}

/** Bean definition kinds */
enum BeanDefinitionKind {
  Singleton = "Singleton",
  Factory = "Factory", 
  Scoped = "Scoped"
}

/** Core bean definition class */
class BeanDefinition<T> {
  scopeQualifier: Qualifier;
  primaryType: any;
  qualifier: Qualifier;
  definition: Definition<T>;
  kind: BeanDefinitionKind;
  secondaryTypes: any[];
}

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