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

qualifiers-parameters.mddocs/

Qualifiers and Parameters

Type-safe dependency identification and parameter injection for complex dependency graphs and runtime configuration.

Capabilities

Qualifier System

Use qualifiers to differentiate between multiple instances of the same type.

interface Qualifier {
  /**
   * Qualifier value for unique identification
   */
  value: any;
}

/**
 * Create named string-based qualifier
 * @param name - Qualifier name
 * @returns StringQualifier instance
 */
function named(name: string): Qualifier;

/**
 * Create type-based qualifier using generics
 * @returns TypeQualifier instance
 */
function named<T>(): Qualifier;

/**
 * Create string qualifier (alias for named)
 * @param name - Qualifier name
 * @returns StringQualifier instance
 */
function qualifier(name: string): Qualifier;

/**
 * Create type qualifier (alias for named)
 * @returns TypeQualifier instance
 */
function qualifier<T>(): Qualifier;

/**
 * Short qualifier function for string
 * @param name - Qualifier name
 * @returns StringQualifier instance
 */
function _q(name: string): Qualifier;

/**
 * Short qualifier function for type
 * @returns TypeQualifier instance
 */
function _q<T>(): Qualifier;

Usage Examples:

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

const databaseModule = module((builder) => {
  // Multiple database connections with qualifiers
  builder.single(named("primary"), () => 
    new DatabaseConnection("primary-db:5432")
  );
  
  builder.single(named("secondary"), () => 
    new DatabaseConnection("secondary-db:5432")
  );
  
  builder.single(named("cache"), () => 
    new DatabaseConnection("redis:6379")
  );
  
  // Multiple loggers with type qualifiers
  builder.single(qualifier("console"), () => new ConsoleLogger());
  builder.single(qualifier("file"), () => new FileLogger("/var/log/app.log"));
  
  // Short syntax qualifiers
  builder.factory(_q("temp"), () => new TemporaryStorage());
  builder.factory(_q("persistent"), () => new PersistentStorage());
});

// Using qualified dependencies
class UserService extends KoinComponent {
  constructor() {
    super();
    this.primaryDb = this.get(named("primary")); // Primary database
    this.cacheDb = this.get(named("cache"));     // Cache database
    this.logger = this.get(qualifier("file"));   // File logger
    this.storage = this.get(_q("persistent"));   // Persistent storage
  }
}

Qualifier Types

Different qualifier implementations for various identification strategies.

/**
 * String-based qualifier for named identification
 */
class StringQualifier implements Qualifier {
  constructor(name: string);
  value: string;
  toString(): string;
}

/**
 * Type-based qualifier for class-based identification
 */
class TypeQualifier implements Qualifier {
  constructor(type: any);
  value: any;
  toString(): string;
}

Usage Examples:

import { StringQualifier, TypeQualifier } from "koin-core";

// Manual qualifier creation
const primaryQualifier = new StringQualifier("primary");
const typeQualifier = new TypeQualifier(DatabaseService);

// Using in module definitions
const manualModule = module((builder) => {
  builder.single(primaryQualifier, () => new PrimaryService());
  builder.single(typeQualifier, () => new DatabaseService());
});

// Qualifier comparison and identification
function logQualifier(qualifier) {
  console.log(`Qualifier: ${qualifier.toString()}`);
  console.log(`Value: ${qualifier.value}`);
}

logQualifier(named("test"));        // "Qualifier: test, Value: test"
logQualifier(named<UserService>()); // "Qualifier: UserService, Value: [class]"

Parameter System

Pass parameters during dependency resolution for dynamic instance creation.

/**
 * Create parameters holder with ordered values
 * @param parameters - Parameter values in injection order
 * @returns ParametersHolder for injection
 */
function parametersOf(...parameters: any[]): ParametersHolder;

/**
 * Create indexed parameter array for array-like access
 * @param parameters - Parameter values
 * @returns ParametersHolder with indexed access
 */
function parameterArrayOf(...parameters: any[]): ParametersHolder;

/**
 * Create parameter set for type-based parameter 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;

Usage Examples:

import { 
  parametersOf, 
  parameterArrayOf, 
  parameterSetOf, 
  emptyParametersHolder 
} from "koin-core";

// Different parameter creation methods
const orderedParams = parametersOf("localhost", 5432, "myapp", true);
const arrayParams = parameterArrayOf("item1", "item2", "item3");
const typedParams = parameterSetOf(new Date(), "config", 100);
const noParams = emptyParametersHolder();

// Usage in dependency injection
class DatabaseService extends KoinComponent {
  async connect(host, port, database, ssl = false) {
    const connection = this.get(named("dynamic"), () => 
      parametersOf(host, port, database, ssl)
    );
    
    return await connection.connect();
  }
}

Parameter Access

Access and retrieve parameters within dependency definitions.

class ParametersHolder {
  /**
   * Get parameter by index with optional type checking
   * @param index - Parameter index (0-based)
   * @param clazz - Optional expected parameter type
   * @returns Parameter value of type T
   * @throws NoParameterFoundException if index out of bounds
   */
  elementAt<T>(index: number, clazz?: new (...args: any[]) => T): T;

  /**
   * Get parameter by type - returns first matching type
   * @returns Parameter value of type T
   * @throws NoParameterFoundException if type not found
   */
  get<T>(): T;

  /**
   * Check if parameters are empty
   * @returns true if no parameters
   */
  isEmpty(): boolean;

  /**
   * Check if parameters exist
   * @returns true if parameters are present
   */
  isNotEmpty(): boolean;

  /**
   * Get parameter count
   * @returns Number of parameters
   */
  size(): number;

  /**
   * Get parameter values as array
   * @returns Array of all parameter values
   */
  values(): any[];
}

Usage Examples:

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

// Module with parameter-accepting definitions
const dynamicModule = module((builder) => {
  builder.factory((scope, params) => {
    // Access parameters by index
    const host = params.elementAt(0);        // string
    const port = params.elementAt(1);        // number
    const ssl = params.elementAt(2);         // boolean
    
    return new DatabaseConnection(host, port, ssl);
  });
  
  builder.single((scope, params) => {
    // Access parameters by type
    const config = params.get(); // ConfigObject
    const logger = params.get(); // Logger
    
    return new ConfigurationService(config, logger);
  });
  
  builder.factory((scope, params) => {
    // Parameter validation and defaults
    if (params.isEmpty()) {
      return new DefaultApiClient();
    }
    
    const baseUrl = params.size() > 0 ? params.elementAt(0) : "https://api.default.com";
    const timeout = params.size() > 1 ? params.elementAt(1) : 5000;
    
    return new ApiClient(baseUrl, timeout);
  });
});

// Using parameters in injection
class ServiceManager extends KoinComponent {
  async createDatabaseConnection(host, port, useSSL) {
    const connection = this.get(named("database"), () => 
      parametersOf(host, port, useSSL)
    );
    
    return connection;
  }
  
  async createConfiguredService() {
    const config = new ConfigObject({ env: "production" });
    const logger = new FileLogger("/var/log/service.log");
    
    const service = this.get(named("configured"), () => 
      parametersOf(config, logger)
    );
    
    return service;
  }
}

Destructuring Support

Use destructuring syntax for convenient parameter access.

class ParametersHolder {
  /**
   * Destructuring support - get first parameter
   * @returns First parameter value
   */
  component1<T>(): T;

  /**
   * Destructuring support - get second parameter
   * @returns Second parameter value
   */
  component2<T>(): T;

  /**
   * Destructuring support - get third parameter
   * @returns Third parameter value
   */
  component3<T>(): T;

  /**
   * Destructuring support - get fourth parameter
   * @returns Fourth parameter value
   */
  component4<T>(): T;

  /**
   * Destructuring support - get fifth parameter
   * @returns Fifth parameter value
   */
  component5<T>(): T;
}

Usage Examples:

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

const destructuringModule = module((builder) => {
  builder.factory((scope, params) => {
    // Destructuring parameter access
    const host = params.component1();     // First parameter
    const port = params.component2();     // Second parameter
    const database = params.component3(); // Third parameter
    const username = params.component4(); // Fourth parameter
    const password = params.component5(); // Fifth parameter
    
    return new DatabaseConfig(host, port, database, username, password);
  });
  
  builder.single((scope, params) => {
    // Mixed access patterns
    const [baseUrl, timeout] = [params.component1(), params.component2()];
    const retries = params.elementAt(2, Number); // Type-checked access
    
    return new HttpClientConfig(baseUrl, timeout, retries);
  });
});

// Usage with destructuring
class ConfigurationManager extends KoinComponent {
  async setupDatabase() {
    const dbConfig = this.get(named("database"), () => 
      parametersOf(
        "prod-db.example.com",
        5432,
        "production_db", 
        "admin",
        "secure_password"
      )
    );
    
    return dbConfig;
  }
}

Parameter Validation and Error Handling

Handle parameter-related errors and validation.

/**
 * Exception thrown when required parameter is not found
 */
class NoParameterFoundException extends Error {
  constructor(message: string);
}

/**
 * Exception thrown when parameter type doesn't match expected
 */
class DefinitionParameterException extends Error {
  constructor(message: string);
}

Usage Examples:

import { 
  module, 
  parametersOf, 
  NoParameterFoundException,
  DefinitionParameterException 
} from "koin-core";

const validatedModule = module((builder) => {
  builder.factory((scope, params) => {
    try {
      // Validate required parameters
      if (params.isEmpty()) {
        throw new DefinitionParameterException("Database parameters required");
      }
      
      if (params.size() < 2) {
        throw new DefinitionParameterException("Host and port parameters required");
      }
      
      const host = params.elementAt(0);
      const port = params.elementAt(1);
      
      // Type validation
      if (typeof host !== 'string') {
        throw new DefinitionParameterException("Host must be string");
      }
      
      if (typeof port !== 'number') {
        throw new DefinitionParameterException("Port must be number");
      }
      
      return new DatabaseConnection(host, port);
      
    } catch (error) {
      if (error instanceof NoParameterFoundException) {
        console.error("Missing required parameter:", error.message);
        return new DatabaseConnection("localhost", 5432); // Default fallback
      }
      throw error;
    }
  });
});

// Safe parameter access
class SafeServiceManager extends KoinComponent {
  async createConnection(host, port) {
    try {
      const connection = this.get(named("validated"), () => 
        parametersOf(host, port)
      );
      return connection;
    } catch (error) {
      if (error instanceof DefinitionParameterException) {
        console.error("Parameter validation failed:", error.message);
        // Handle gracefully or re-throw
        throw new Error(`Failed to create connection: ${error.message}`);
      }
      throw error;
    }
  }
}

Types

/** Function type for parameter definitions */
type ParametersDefinition = () => ParametersHolder;

/** Qualifier value type - can be any type */
type QualifierValue = any;

/** String-based qualifier implementation */
class StringQualifier implements Qualifier {
  value: string;
  constructor(name: string);
}

/** Type-based qualifier implementation */
class TypeQualifier implements Qualifier {
  value: any;
  constructor(type: any);
}

/** Parameter holder for dependency injection */
class ParametersHolder {
  values(): any[];
  elementAt<T>(index: number, clazz?: new (...args: any[]) => T): T;
  get<T>(): T;
  isEmpty(): boolean;
  isNotEmpty(): boolean;
  size(): number;
  component1<T>(): T;
  component2<T>(): T;
  component3<T>(): T;
  component4<T>(): T;
  component5<T>(): T;
}

/** Exception for missing parameters */
class NoParameterFoundException extends Error {
  constructor(message: string);
}

/** Exception for parameter definition errors */
class DefinitionParameterException 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