Skip to content

Bootstrapping API Reference

API Reference: Classes, interfaces, and utilities for application bootstrapping

Table of Contents

Prerequisites

Before reading this document, you should understand:

Interfaces

IBootableApplication

Interface that applications must implement to support bootstrapping.

typescript
interface IBootableApplication {
  boot(): Promise<IBootReport>;
}
MemberTypeDescription
boot()() => Promise<IBootReport>Execute boot process

Example:

typescript
export class Application extends BaseApplication implements IBootableApplication {
  async boot() {
    const bootstrapper = this.get<Bootstrapper>({ key: 'bootstrapper' });
    return bootstrapper.boot({});
  }
}

Note: The BootMixin adds an optional bootOptions?: IBootOptions property to the mixed class, but it is not part of the IBootableApplication interface itself.

IBootOptions

Configuration for artifact discovery per artifact type.

typescript
interface IBootOptions {
  controllers?: IArtifactOptions;
  services?: IArtifactOptions;
  repositories?: IArtifactOptions;
  datasources?: IArtifactOptions;
  [artifactType: string]: IArtifactOptions | undefined;
}
PropertyTypeDescription
controllersIArtifactOptions | undefinedController discovery config
servicesIArtifactOptions | undefinedService discovery config
repositoriesIArtifactOptions | undefinedRepository discovery config
datasourcesIArtifactOptions | undefinedDatasource discovery config
[key]IArtifactOptions | undefinedCustom artifact type config

Example:

typescript
const bootOptions: IBootOptions = {
  controllers: {
    dirs: ['controllers/private', 'controllers/public'],
    extensions: ['.controller.js'],
    isNested: true
  },
  services: {
    glob: 'features/**/*.service.js'
  },
  // Custom artifact type
  middlewares: {
    dirs: ['middlewares'],
    extensions: ['.middleware.js']
  }
};

IArtifactOptions

Configuration for discovering a specific artifact type.

typescript
interface IArtifactOptions {
  dirs?: string[];
  extensions?: string[];
  isNested?: boolean;
  glob?: string;
}
PropertyTypeDefaultDescription
dirsstring[]undefinedDirectories to scan (relative to project root)
extensionsstring[]undefinedFile extensions to match (e.g., ['.controller.js'])
isNestedbooleantrueScan subdirectories recursively
globstringundefinedCustom glob pattern (overrides dirs/extensions)

Example:

typescript
const artifactOptions: IArtifactOptions = {
  dirs: ['controllers/v1', 'controllers/v2'],
  extensions: ['.controller.js', '.controller.ts'],
  isNested: true
};

// Or with custom glob
const customOptions: IArtifactOptions = {
  glob: 'src/**/api/*.controller.{js,ts}'
};

IBooter

Interface that all booters must implement.

typescript
interface IBooter {
  configure(): ValueOrPromise<void>;
  discover(): ValueOrPromise<void>;
  load(): ValueOrPromise<void>;
}

Note: ValueOrPromise<T> is T | Promise<T>. While the interface requires all three methods, the Bootstrapper gracefully skips any phase method that is not a function at runtime, so partial implementations are tolerated in practice.

MethodPhaseDescription
configure()ConfigureSetup discovery patterns and options
discover()DiscoverScan filesystem for matching artifacts
load()LoadLoad classes and bind to container

Example:

typescript
export class CustomBooter implements IBooter {
  async configure() {
    // Setup patterns
  }
  
  async discover() {
    // Scan filesystem
  }
  
  async load() {
    // Load and bind classes
  }
}

IBooterOptions

Constructor options for booters.

typescript
interface IBooterOptions {
  scope: string;
  root: string;
  artifactOptions: IArtifactOptions;
}
PropertyTypeDescription
scopestringLogger scope (usually class name)
rootstringProject root directory path
artifactOptionsIArtifactOptionsArtifact discovery configuration

Example:

typescript
const options: IBooterOptions = {
  scope: 'ControllerBooter',
  root: '/path/to/project',
  artifactOptions: {
    dirs: ['controllers'],
    extensions: ['.controller.js']
  }
};

IBootExecutionOptions

Options for controlling boot execution.

typescript
interface IBootExecutionOptions {
  phases?: TBootPhase[];
  booters?: string[];
}
PropertyTypeDefaultDescription
phasesTBootPhase[]['configure', 'discover', 'load']Boot phases to execute
bootersstring[]undefinedSpecific booters to run (by name)

Example:

typescript
// Run only discover phase
await bootstrapper.boot({
  phases: ['discover']
});

// Run only specific booters
await bootstrapper.boot({
  booters: ['ControllerBooter', 'ServiceBooter']
});

// Combine both
await bootstrapper.boot({
  phases: ['configure', 'discover'],
  booters: ['ControllerBooter']
});

IBootstrapper

Interface for the bootstrapper orchestrator.

typescript
interface IBootstrapper {
  boot(opts: IBootExecutionOptions): Promise<IBootReport>;
}
MethodReturnDescription
boot(opts)Promise<IBootReport>Execute boot process with options

IBootReport

Report generated after boot completion.

typescript
interface IBootReport {}

Currently an empty interface, reserved for future enhancements (timing, errors, artifact counts, etc.).

IApplication

Extended Container interface with application-specific methods.

typescript
interface IApplication extends Container {
  getProjectRoot(): string;
}
MethodReturnDescription
getProjectRoot()stringGet absolute path to project root

Classes

Bootstrapper

Orchestrates the boot process by discovering and executing booters.

typescript
export class Bootstrapper extends BaseHelper implements IBootstrapper

Constructor

typescript
constructor(
  @inject({ key: '@app/instance' }) application: IApplication
)
ParameterTypeDescription
applicationIApplicationApplication instance (injected)

Methods

boot()

Execute the boot process.

typescript
async boot(opts: IBootExecutionOptions): Promise<IBootReport>
ParameterTypeDescription
optsIBootExecutionOptionsBoot execution options

Returns: Promise<IBootReport> - Boot completion report

Example:

typescript
const bootstrapper = app.get<Bootstrapper>({ key: 'bootstrapper' });

// Full boot
await bootstrapper.boot({});

// Partial boot
await bootstrapper.boot({
  phases: ['discover'],
  booters: ['ControllerBooter']
});
discoverBooters() [private]

Discovers all booters registered in the application container.

typescript
private async discoverBooters(): Promise<void>

Finds all bindings tagged with 'booter' and instantiates them.

runPhase() [private]

Executes a specific boot phase on all booters.

typescript
private async runPhase(opts: { phase: TBootPhase; booterNames?: string[] }): Promise<void>
generateReport() [private]

Generates boot completion report.

typescript
private generateReport(): IBootReport

BaseArtifactBooter

Abstract base class for creating artifact booters.

typescript
export abstract class BaseArtifactBooter extends BaseHelper implements IBooter

Constructor

typescript
constructor(opts: IBooterOptions)
ParameterTypeDescription
optsIBooterOptionsBooter configuration

Abstract Methods

getDefaultDirs()

Return default directories to scan.

typescript
protected abstract getDefaultDirs(): string[]

Example:

typescript
protected getDefaultDirs(): string[] {
  return ['controllers'];
}
getDefaultExtensions()

Return default file extensions to match.

typescript
protected abstract getDefaultExtensions(): string[]

Example:

typescript
protected getDefaultExtensions(): string[] {
  return ['.controller.js'];
}
bind()

Bind loaded classes to application container.

typescript
protected abstract bind(): Promise<void>

Example:

typescript
protected async bind(): Promise<void> {
  for (const cls of this.loadedClasses) {
    this.application.bind({ key: `controllers.${cls.name}` }).toClass(cls);
  }
}

Implemented Methods

configure()

Configure discovery patterns using defaults or provided options.

typescript
async configure(): Promise<void>
discover()

Scan filesystem for artifacts matching the pattern.

typescript
async discover(): Promise<void>
load()

Load discovered classes and bind them to container.

typescript
async load(): Promise<void>
getPattern()

Generate glob pattern from artifact options.

typescript
protected getPattern(): string

Returns: Glob pattern string. Examples:

  • Single dir/ext: controllers/{**/*,*}.controller.js
  • Multiple dirs/exts: {dir1,dir2}/{**/*,*}.{ext1,ext2}
  • Non-nested (isNested: false): controllers/*.controller.js
  • Custom glob option overrides pattern generation entirely

Note: The nested pattern {**/*,*} currently supports one level of nesting.

Properties

PropertyTypeDescription
rootstringProject root directory
artifactOptionsIArtifactOptionsArtifact discovery config
discoveredFilesstring[]Array of discovered file paths
loadedClassesTClass<any>[]Array of loaded class constructors

ControllerBooter

Built-in booter for discovering controllers.

typescript
export class ControllerBooter extends BaseArtifactBooter

Constructor

typescript
constructor(
  @inject({ key: '@app/project_root' }) root: string,
  @inject({ key: '@app/instance' }) application: IApplication,
  @inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)

Defaults

SettingValue
Directories['controllers']
Extensions['.controller.js']
Binding Keycontrollers.{ClassName}

ServiceBooter

Built-in booter for discovering services.

typescript
export class ServiceBooter extends BaseArtifactBooter

Constructor

typescript
constructor(
  @inject({ key: '@app/project_root' }) root: string,
  @inject({ key: '@app/instance' }) application: IApplication,
  @inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)

Defaults

SettingValue
Directories['services']
Extensions['.service.js']
Binding Keyservices.{ClassName}

RepositoryBooter

Built-in booter for discovering repositories.

typescript
export class RepositoryBooter extends BaseArtifactBooter

Constructor

typescript
constructor(
  @inject({ key: '@app/project_root' }) root: string,
  @inject({ key: '@app/instance' }) application: IApplication,
  @inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)

Defaults

SettingValue
Directories['repositories']
Extensions['.repository.js']
Binding Keyrepositories.{ClassName}

DatasourceBooter

Built-in booter for discovering datasources.

typescript
export class DatasourceBooter extends BaseArtifactBooter

Constructor

typescript
constructor(
  @inject({ key: '@app/project_root' }) root: string,
  @inject({ key: '@app/instance' }) application: IApplication,
  @inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)

Defaults

SettingValue
Directories['datasources']
Extensions['.datasource.js']
Binding Keydatasources.{ClassName}
Binding Scopesingleton

Key difference: DatasourceBooter is the only built-in booter that sets bindings to singleton scope (via .setScope('singleton')). This ensures connection pooling and resource sharing across the application. All other booters use the default transient scope.

Types

TBootPhase

Boot execution phases.

typescript
type TBootPhase = 'configure' | 'discover' | 'load'

Values:

  • 'configure' - Setup phase
  • 'discover' - File discovery phase
  • 'load' - Class loading and binding phase

TClass

Generic class constructor type.

typescript
type TClass<T> = TConstructor<T> & { [property: string]: any }

TConstructor

Constructor function type.

typescript
type TConstructor<T> = new (...args: any[]) => T

TAbstractConstructor

Abstract constructor type.

typescript
type TAbstractConstructor<T> = abstract new (...args: any[]) => T

Utilities

discoverFiles()

Discover files matching a glob pattern.

typescript
async function discoverFiles(opts: {
  pattern: string;
  root: string;
}): Promise<string[]>
ParameterTypeDescription
patternstringGlob pattern to match
rootstringRoot directory for search

Returns: Promise<string[]> - Array of absolute file paths

Example:

typescript
const files = await discoverFiles({
  pattern: 'controllers/**/*.controller.js',
  root: '/path/to/project'
});
// ['/path/to/project/controllers/user.controller.js', ...]

loadClasses()

Load class constructors from files.

typescript
async function loadClasses(opts: {
  files: string[];
  root: string;
}): Promise<AnyType[]>
ParameterTypeDescription
filesstring[]Array of file paths to load
rootstringProject root (for error messages)

Returns: Promise<AnyType[]> - Array of loaded class constructors (filtered by isClass type guard)

Example:

typescript
const classes = await loadClasses({
  files: [
    '/path/to/project/controllers/user.controller.js',
    '/path/to/project/controllers/product.controller.js'
  ],
  root: '/path/to/project'
});
// [UserController, ProductController]

isClass()

Type guard to check if value is a class constructor.

typescript
function isClass<T>(target: any): target is TClass<T>
ParameterTypeDescription
targetanyValue to check

Returns: boolean - True if target is a class constructor

Example:

typescript
const module = await import('./user.controller.js');

for (const exported of Object.values(module)) {
  if (isClass(exported)) {
    // exported is TClass<any>
    console.log(exported.name); // "UserController"
  }
}

Constants

BootPhases

Static class defining boot phase constants.

typescript
class BootPhases {
  static readonly CONFIGURE = 'configure';
  static readonly DISCOVER = 'discover';
  static readonly LOAD = 'load';
}

BOOT_PHASES

Array of all boot phases in execution order (derived from BootPhases).

typescript
const BOOT_PHASES: TBootPhase[] = ['configure', 'discover', 'load']

Usage:

typescript
import { BOOT_PHASES } from '@venizia/ignis-boot';

await bootstrapper.boot({ phases: BOOT_PHASES });

Mixin Functions

BootMixin()

Mixin that adds bootable capability to applications.

typescript
function BootMixin<T extends TMixinTarget<Container>>(
  baseClass: T
): typeof baseClass & IBootableApplication
ParameterTypeDescription
baseClassT extends TMixinTarget<Container>Base class to extend

Returns: Mixed class implementing IBootableApplication

Auto-registers in constructor:

  • @app/boot-options -- user boot config (from this.bootOptions)
  • booter.DatasourceBooter -- tagged 'booter'
  • booter.RepositoryBooter -- tagged 'booter'
  • booter.ServiceBooter -- tagged 'booter'
  • booter.ControllerBooter -- tagged 'booter'
  • bootstrapper -- singleton Bootstrapper instance

Example:

typescript
import { BootMixin } from '@venizia/ignis-boot';
import { Container } from '@venizia/ignis-inversion';

class MyApp extends BootMixin(Container) {
  bootOptions = {
    controllers: { dirs: ['controllers'] }
  };
}

const app = new MyApp();
await app.boot();

Note: BaseApplication does not use BootMixin. Instead, it registers the same booters and bootstrapper in its own registerBooters() method using this.booter() and reads boot options from this.configs.bootOptions.

See Also