Bootstrapping API Reference
API Reference: Classes, interfaces, and utilities for application bootstrapping
Table of Contents
Prerequisites
Before reading this document, you should understand:
- IGNIS Application - Application lifecycle and initialization
- Dependency Injection - DI container and bindings
- Controllers, Services, and Repositories - Core abstractions
- Convention-based programming patterns
Interfaces
IBootableApplication
Interface that applications must implement to support bootstrapping.
interface IBootableApplication {
boot(): Promise<IBootReport>;
}| Member | Type | Description |
|---|---|---|
boot() | () => Promise<IBootReport> | Execute boot process |
Example:
export class Application extends BaseApplication implements IBootableApplication {
async boot() {
const bootstrapper = this.get<Bootstrapper>({ key: 'bootstrapper' });
return bootstrapper.boot({});
}
}Note: The
BootMixinadds an optionalbootOptions?: IBootOptionsproperty to the mixed class, but it is not part of theIBootableApplicationinterface itself.
IBootOptions
Configuration for artifact discovery per artifact type.
interface IBootOptions {
controllers?: IArtifactOptions;
services?: IArtifactOptions;
repositories?: IArtifactOptions;
datasources?: IArtifactOptions;
[artifactType: string]: IArtifactOptions | undefined;
}| Property | Type | Description |
|---|---|---|
controllers | IArtifactOptions | undefined | Controller discovery config |
services | IArtifactOptions | undefined | Service discovery config |
repositories | IArtifactOptions | undefined | Repository discovery config |
datasources | IArtifactOptions | undefined | Datasource discovery config |
[key] | IArtifactOptions | undefined | Custom artifact type config |
Example:
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.
interface IArtifactOptions {
dirs?: string[];
extensions?: string[];
isNested?: boolean;
glob?: string;
}| Property | Type | Default | Description |
|---|---|---|---|
dirs | string[] | undefined | Directories to scan (relative to project root) |
extensions | string[] | undefined | File extensions to match (e.g., ['.controller.js']) |
isNested | boolean | true | Scan subdirectories recursively |
glob | string | undefined | Custom glob pattern (overrides dirs/extensions) |
Example:
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.
interface IBooter {
configure(): ValueOrPromise<void>;
discover(): ValueOrPromise<void>;
load(): ValueOrPromise<void>;
}Note:
ValueOrPromise<T>isT | Promise<T>. While the interface requires all three methods, theBootstrappergracefully skips any phase method that is not a function at runtime, so partial implementations are tolerated in practice.
| Method | Phase | Description |
|---|---|---|
configure() | Configure | Setup discovery patterns and options |
discover() | Discover | Scan filesystem for matching artifacts |
load() | Load | Load classes and bind to container |
Example:
export class CustomBooter implements IBooter {
async configure() {
// Setup patterns
}
async discover() {
// Scan filesystem
}
async load() {
// Load and bind classes
}
}IBooterOptions
Constructor options for booters.
interface IBooterOptions {
scope: string;
root: string;
artifactOptions: IArtifactOptions;
}| Property | Type | Description |
|---|---|---|
scope | string | Logger scope (usually class name) |
root | string | Project root directory path |
artifactOptions | IArtifactOptions | Artifact discovery configuration |
Example:
const options: IBooterOptions = {
scope: 'ControllerBooter',
root: '/path/to/project',
artifactOptions: {
dirs: ['controllers'],
extensions: ['.controller.js']
}
};IBootExecutionOptions
Options for controlling boot execution.
interface IBootExecutionOptions {
phases?: TBootPhase[];
booters?: string[];
}| Property | Type | Default | Description |
|---|---|---|---|
phases | TBootPhase[] | ['configure', 'discover', 'load'] | Boot phases to execute |
booters | string[] | undefined | Specific booters to run (by name) |
Example:
// 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.
interface IBootstrapper {
boot(opts: IBootExecutionOptions): Promise<IBootReport>;
}| Method | Return | Description |
|---|---|---|
boot(opts) | Promise<IBootReport> | Execute boot process with options |
IBootReport
Report generated after boot completion.
interface IBootReport {}Currently an empty interface, reserved for future enhancements (timing, errors, artifact counts, etc.).
IApplication
Extended Container interface with application-specific methods.
interface IApplication extends Container {
getProjectRoot(): string;
}| Method | Return | Description |
|---|---|---|
getProjectRoot() | string | Get absolute path to project root |
Classes
Bootstrapper
Orchestrates the boot process by discovering and executing booters.
export class Bootstrapper extends BaseHelper implements IBootstrapperConstructor
constructor(
@inject({ key: '@app/instance' }) application: IApplication
)| Parameter | Type | Description |
|---|---|---|
application | IApplication | Application instance (injected) |
Methods
boot()
Execute the boot process.
async boot(opts: IBootExecutionOptions): Promise<IBootReport>| Parameter | Type | Description |
|---|---|---|
opts | IBootExecutionOptions | Boot execution options |
Returns: Promise<IBootReport> - Boot completion report
Example:
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.
private async discoverBooters(): Promise<void>Finds all bindings tagged with 'booter' and instantiates them.
runPhase() [private]
Executes a specific boot phase on all booters.
private async runPhase(opts: { phase: TBootPhase; booterNames?: string[] }): Promise<void>generateReport() [private]
Generates boot completion report.
private generateReport(): IBootReportBaseArtifactBooter
Abstract base class for creating artifact booters.
export abstract class BaseArtifactBooter extends BaseHelper implements IBooterConstructor
constructor(opts: IBooterOptions)| Parameter | Type | Description |
|---|---|---|
opts | IBooterOptions | Booter configuration |
Abstract Methods
getDefaultDirs()
Return default directories to scan.
protected abstract getDefaultDirs(): string[]Example:
protected getDefaultDirs(): string[] {
return ['controllers'];
}getDefaultExtensions()
Return default file extensions to match.
protected abstract getDefaultExtensions(): string[]Example:
protected getDefaultExtensions(): string[] {
return ['.controller.js'];
}bind()
Bind loaded classes to application container.
protected abstract bind(): Promise<void>Example:
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.
async configure(): Promise<void>discover()
Scan filesystem for artifacts matching the pattern.
async discover(): Promise<void>load()
Load discovered classes and bind them to container.
async load(): Promise<void>getPattern()
Generate glob pattern from artifact options.
protected getPattern(): stringReturns: 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
globoption overrides pattern generation entirely
Note: The nested pattern
{**/*,*}currently supports one level of nesting.
Properties
| Property | Type | Description |
|---|---|---|
root | string | Project root directory |
artifactOptions | IArtifactOptions | Artifact discovery config |
discoveredFiles | string[] | Array of discovered file paths |
loadedClasses | TClass<any>[] | Array of loaded class constructors |
ControllerBooter
Built-in booter for discovering controllers.
export class ControllerBooter extends BaseArtifactBooterConstructor
constructor(
@inject({ key: '@app/project_root' }) root: string,
@inject({ key: '@app/instance' }) application: IApplication,
@inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)Defaults
| Setting | Value |
|---|---|
| Directories | ['controllers'] |
| Extensions | ['.controller.js'] |
| Binding Key | controllers.{ClassName} |
ServiceBooter
Built-in booter for discovering services.
export class ServiceBooter extends BaseArtifactBooterConstructor
constructor(
@inject({ key: '@app/project_root' }) root: string,
@inject({ key: '@app/instance' }) application: IApplication,
@inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)Defaults
| Setting | Value |
|---|---|
| Directories | ['services'] |
| Extensions | ['.service.js'] |
| Binding Key | services.{ClassName} |
RepositoryBooter
Built-in booter for discovering repositories.
export class RepositoryBooter extends BaseArtifactBooterConstructor
constructor(
@inject({ key: '@app/project_root' }) root: string,
@inject({ key: '@app/instance' }) application: IApplication,
@inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)Defaults
| Setting | Value |
|---|---|
| Directories | ['repositories'] |
| Extensions | ['.repository.js'] |
| Binding Key | repositories.{ClassName} |
DatasourceBooter
Built-in booter for discovering datasources.
export class DatasourceBooter extends BaseArtifactBooterConstructor
constructor(
@inject({ key: '@app/project_root' }) root: string,
@inject({ key: '@app/instance' }) application: IApplication,
@inject({ key: '@app/boot-options' }) bootOptions: IBootOptions
)Defaults
| Setting | Value |
|---|---|
| Directories | ['datasources'] |
| Extensions | ['.datasource.js'] |
| Binding Key | datasources.{ClassName} |
| Binding Scope | singleton |
Key difference:
DatasourceBooteris the only built-in booter that sets bindings tosingletonscope (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.
type TBootPhase = 'configure' | 'discover' | 'load'Values:
'configure'- Setup phase'discover'- File discovery phase'load'- Class loading and binding phase
TClass
Generic class constructor type.
type TClass<T> = TConstructor<T> & { [property: string]: any }TConstructor
Constructor function type.
type TConstructor<T> = new (...args: any[]) => TTAbstractConstructor
Abstract constructor type.
type TAbstractConstructor<T> = abstract new (...args: any[]) => TUtilities
discoverFiles()
Discover files matching a glob pattern.
async function discoverFiles(opts: {
pattern: string;
root: string;
}): Promise<string[]>| Parameter | Type | Description |
|---|---|---|
pattern | string | Glob pattern to match |
root | string | Root directory for search |
Returns: Promise<string[]> - Array of absolute file paths
Example:
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.
async function loadClasses(opts: {
files: string[];
root: string;
}): Promise<AnyType[]>| Parameter | Type | Description |
|---|---|---|
files | string[] | Array of file paths to load |
root | string | Project root (for error messages) |
Returns: Promise<AnyType[]> - Array of loaded class constructors (filtered by isClass type guard)
Example:
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.
function isClass<T>(target: any): target is TClass<T>| Parameter | Type | Description |
|---|---|---|
target | any | Value to check |
Returns: boolean - True if target is a class constructor
Example:
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.
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).
const BOOT_PHASES: TBootPhase[] = ['configure', 'discover', 'load']Usage:
import { BOOT_PHASES } from '@venizia/ignis-boot';
await bootstrapper.boot({ phases: BOOT_PHASES });Mixin Functions
BootMixin()
Mixin that adds bootable capability to applications.
function BootMixin<T extends TMixinTarget<Container>>(
baseClass: T
): typeof baseClass & IBootableApplication| Parameter | Type | Description |
|---|---|---|
baseClass | T extends TMixinTarget<Container> | Base class to extend |
Returns: Mixed class implementing IBootableApplication
Auto-registers in constructor:
@app/boot-options-- user boot config (fromthis.bootOptions)booter.DatasourceBooter-- tagged'booter'booter.RepositoryBooter-- tagged'booter'booter.ServiceBooter-- tagged'booter'booter.ControllerBooter-- tagged'booter'bootstrapper-- singletonBootstrapperinstance
Example:
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:
BaseApplicationdoes not useBootMixin. Instead, it registers the same booters and bootstrapper in its ownregisterBooters()method usingthis.booter()and reads boot options fromthis.configs.bootOptions.
See Also
Related References:
- Application - Application lifecycle and initialization
- Dependency Injection - DI container and bindings
- Components - Pluggable modules and components
Guides:
Best Practices:
Configuration: