container.ts
Version:
Modular application framework
155 lines (154 loc) • 6.54 kB
TypeScript
import { AwilixContainer } from "awilix";
import * as Debug from "debug";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { ErrorChain } from "../lib/error";
import { Environment } from "./environment";
import { ELogLevel, ILogMessage, ILogMetadata } from "./log";
import { EMetricType, IMetricTags } from "./metric";
import { Module } from "./module";
/** Command line arguments interface. */
export interface IContainerArguments {
/** Non-option arguments. */
arguments: string[];
/** All remaining options. */
options: object;
}
/** Container error codes. */
export declare enum EContainerError {
Up = "ContainerError.Up",
Down = "ContainerError.Down",
ModuleRegistered = "ContainerError.ModuleRegistered"
}
/** Container error class. */
export declare class ContainerError extends ErrorChain {
constructor(code: EContainerError, cause?: Error, context?: object);
}
/** Container log message interface. */
export interface IContainerLogMessage {
level: ELogLevel;
message: ILogMessage;
metadata: ILogMetadata;
args: any[];
}
/** Log message class for stream of module logs. */
export declare class ContainerLogMessage implements IContainerLogMessage {
readonly level: ELogLevel;
readonly message: ILogMessage;
readonly metadata: ILogMetadata;
readonly args: any[];
constructor(level: ELogLevel, message: ILogMessage, metadata: ILogMetadata, args: any[]);
}
/** Container metric message interface. */
export interface IContainerMetricMessage {
type: EMetricType;
name: string;
value: any;
tags: IMetricTags;
args: any[];
}
/** Metric message class for stream of module metrics. */
export declare class ContainerMetricMessage implements IContainerMetricMessage {
readonly type: EMetricType;
readonly name: string;
readonly value: any;
readonly tags: IMetricTags;
readonly args: any[];
constructor(type: EMetricType, name: string, value: any, tags: IMetricTags, args: any[]);
}
/** Container log names. */
export declare enum EContainerLog {
Up = "Container.Up",
Down = "Container.Down"
}
/** Container scope keys. */
export declare enum EContainerScope {
/** Container reference name resolved internally by modules. */
Container = "Container"
}
/**
* Container class.
* Wrapper around awilix library.
*/
export declare class Container {
/** Required container name, used to namespace modules. */
readonly name: string;
/** Optional container environment. */
readonly environment: Environment;
/** Optional command line arguments. */
readonly argv: IContainerArguments;
/** Root container. */
readonly container: AwilixContainer;
/** Observable module state. */
readonly modules$: BehaviorSubject<{
[key: string]: boolean;
}>;
/** Array of registered module names. */
get moduleNames(): string[];
/** Array of registered modules. */
get modules(): Module[];
/** Container module logs. */
readonly logs$: Subject<ContainerLogMessage>;
/** Container module metrics. */
readonly metrics$: Subject<ContainerMetricMessage>;
/** Module debug interface. */
readonly debug: Debug.IDebugger;
/** Creates a new container in proxy resolution mode. */
constructor(
/** Required container name, used to namespace modules. */
name: string,
/** Optional container environment. */
environment?: Environment,
/** Optional command line arguments. */
argv?: IContainerArguments);
/** Create scoped container from root container. */
createScope(): AwilixContainer;
/**
* Register a module in container.
* Throws an error if module of name is already registered.
*/
registerModule<T extends typeof Module>(moduleClass: T): Container;
/** Register named modules in container. */
registerModules<T extends typeof Module>(modules: T[]): Container;
/** Register a value of type in container. */
registerValue<T>(name: string, value: T): Container;
/** Resolve value or module of type from container by name. */
resolve<T>(name: string): T;
/** Send log message of level for module. */
sendLog(level: ELogLevel, message: ILogMessage, metadata: ILogMetadata, args: any[]): void;
/** Send metric message of type for module. */
sendMetric(type: EMetricType, name: string, value: any, tags: IMetricTags, args: any[]): void;
/** Observable stream of module logs filtered by level. */
filterLogs(level: ELogLevel): Observable<ContainerLogMessage>;
/** Observable stream of module metrics filtered by type. */
filterMetrics(type: EMetricType): Observable<ContainerMetricMessage>;
/**
* Signal modules to enter operational state.
* Module hook method `moduleUp` called in order of dependencies.
*/
up(timeout?: number): Promise<number>;
/**
* Signal modules to leave operational state.
* Module hook method `moduleDown` called in order of dependents.
*/
down(timeout?: number): Promise<number>;
/** Call modules destroy hooks before process exit. */
destroy(): void;
/** Wait for modules to enter operational state before calling next. */
protected containerWhenModulesUp(...modules: string[]): Promise<void>;
/** Wait for modules to leave operational state before calling next. */
protected containerWhenModulesDown(...modules: string[]): Promise<void>;
/** Create a new instance of module class. */
protected containerModuleFactory<T extends typeof Module>(moduleClass: T, opts: any): Module;
/** Returns list of module names which are dependencies of target module. */
protected containerModuleDependencies(mod: Module): string[];
/** Returns list of module names which are dependents of target module. */
protected containerModuleDependents(mod: Module): string[];
/** Returns true if module is already registered in container. */
protected containerModuleRegistered(name: string): boolean;
/** Wrap module hook promise with timeout operator, call containerModuleState on next. */
protected containerModuleStateTimeout(hook: Promise<void>, moduleName: string, state: boolean, timeout?: number): Promise<void>;
/** Update observable modules state for target module. */
protected containerModuleState(name: string, state: boolean): void;
/** Internal handler for `up` and `down` methods of class. */
protected containerState(hooks: Promise<void>[], state: boolean): Promise<number>;
}