Define and implement core constructs such as Application and Component for LoopBack 4 framework
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The Application class is the central container for LoopBack 4 applications, extending Context to provide a complete IoC container with lifecycle management. It serves as the main entry point for registering components, servers, controllers, and services.
Creates a new Application instance with optional configuration and parent context.
/**
* Create an application with the given parent context
*/
constructor(parent: Context);
/**
* Create an application with the given configuration and parent context
*/
constructor(config?: ApplicationConfig, parent?: Context);Usage Examples:
import { Application } from "@loopback/core";
// Basic application
const app = new Application();
// Application with configuration
const app = new Application({
name: 'my-service',
shutdown: {
signals: ['SIGTERM', 'SIGINT'],
gracePeriod: 5000
}
});
// Application with parent context
const parentContext = new Context();
const app = new Application(parentContext);
// Application with both config and parent
const app = new Application({
name: 'child-service'
}, parentContext);Register components that contribute controllers, providers, servers, and other resources to the application.
/**
* Add a component to this application and register extensions such as
* controllers, providers, and servers from the component.
*/
component<T extends Component = Component>(
componentCtor: Constructor<T>,
nameOrOptions?: string | BindingFromClassOptions
): Binding<T>;Usage Examples:
import { Application, Component } from "@loopback/core";
class ProductComponent implements Component {
controllers = [ProductController];
repositories = [ProductRepository];
providers = {
'services.productService': ProductServiceProvider
};
}
// Register the component
const app = new Application();
app.component(ProductComponent);
// Register with custom name
app.component(ProductComponent, 'products');
// Register with options
app.component(ProductComponent, {
name: 'product-component',
namespace: 'products'
});Register and manage server instances for handling different protocols (REST, GraphQL, gRPC, etc.).
/**
* Bind a Server constructor to the Application's master context.
* Each server constructor added in this way must provide a unique prefix
* to prevent binding overlap.
*/
server<T extends Server>(
ctor: Constructor<T>,
nameOrOptions?: string | BindingFromClassOptions
): Binding<T>;
/**
* Bind an array of Server constructors to the Application's master context.
*/
servers<T extends Server>(ctors: Constructor<T>[]): Binding[];
/**
* Retrieve the singleton instance for a bound server.
*/
getServer<T extends Server>(target: Constructor<T> | string): Promise<T>;Usage Examples:
import { Application, Server } from "@loopback/core";
class RestServer implements Server {
listening = false;
async start(): Promise<void> {
// Start REST server logic
this.listening = true;
}
async stop(): Promise<void> {
// Stop REST server logic
this.listening = false;
}
}
const app = new Application();
// Register single server
app.server(RestServer);
// Register with custom name
app.server(RestServer, 'api-server');
// Register multiple servers
app.servers([RestServer, GraphQLServer]);
// Retrieve server instance
const restServer = await app.getServer(RestServer);
const namedServer = await app.getServer('api-server');Register controller classes that handle HTTP requests and other application logic.
/**
* Register a controller class with this application.
*/
controller<T>(
controllerCtor: ControllerClass<T>,
nameOrOptions?: string | BindingFromClassOptions
): Binding<T>;Usage Examples:
import { Application } from "@loopback/core";
class UserController {
async getUsers(): Promise<User[]> {
// Controller logic
return [];
}
}
const app = new Application();
// Register controller
app.controller(UserController);
// Register with custom name
app.controller(UserController, 'users');
// Register with options
app.controller(UserController, {
name: 'user-controller',
namespace: 'controllers'
});Register service classes and providers for dependency injection throughout the application.
/**
* Add a service to this application.
*/
service<S>(
cls: ServiceOrProviderClass<S>,
nameOrOptions?: string | ServiceOptions
): Binding<S>;Usage Examples:
import { Application, service, Provider } from "@loopback/core";
// Service class
class EmailService {
async sendEmail(to: string, subject: string, body: string): Promise<void> {
// Email sending logic
}
}
// Provider class
class ConfigProvider implements Provider<AppConfig> {
value(): AppConfig {
return {
apiUrl: process.env.API_URL || 'http://localhost:3000'
};
}
}
const app = new Application();
// Register service class
app.service(EmailService);
// Register provider
app.service(ConfigProvider, 'config');
// Register with service interface
app.service(EmailService, {
interface: Symbol.for('EmailService')
});Manage application lifecycle with coordinated initialization, start, and stop sequences.
/**
* Initialize the application, and all of its registered observers.
*/
init(): Promise<void>;
/**
* Start the application, and all of its registered observers.
*/
start(): Promise<void>;
/**
* Stop the application instance and all of its registered observers.
*/
stop(): Promise<void>;
/**
* Register a function to be called when the application initializes.
*/
onInit(fn: () => ValueOrPromise<void>): Binding<LifeCycleObserver>;
/**
* Register a function to be called when the application starts.
*/
onStart(fn: () => ValueOrPromise<void>): Binding<LifeCycleObserver>;
/**
* Register a function to be called when the application stops.
*/
onStop(fn: () => ValueOrPromise<void>): Binding<LifeCycleObserver>;
/**
* Get the state of the application.
*/
readonly state: string;Usage Examples:
import { Application } from "@loopback/core";
const app = new Application();
// Register lifecycle hooks
app.onInit(async () => {
console.log('Application is initializing...');
});
app.onStart(async () => {
console.log('Application is starting...');
});
app.onStop(async () => {
console.log('Application is stopping...');
});
// Manual lifecycle management
await app.init(); // State: 'initialized'
await app.start(); // State: 'started'
await app.stop(); // State: 'stopped'
// Check application state
console.log(app.state); // 'created', 'initialized', 'started', 'stopped', etc.Register classes that implement the LifeCycleObserver interface for coordinated startup and shutdown.
/**
* Register a life cycle observer class
*/
lifeCycleObserver<T extends LifeCycleObserver>(
ctor: Constructor<T>,
nameOrOptions?: string | BindingFromClassOptions
): Binding<T>;Usage Examples:
import { Application, LifeCycleObserver, lifeCycleObserver } from "@loopback/core";
@lifeCycleObserver('database')
class DatabaseObserver implements LifeCycleObserver {
async init(): Promise<void> {
console.log('Initializing database connection...');
}
async start(): Promise<void> {
console.log('Database connection started');
}
async stop(): Promise<void> {
console.log('Closing database connection...');
}
}
const app = new Application();
// Register lifecycle observer
app.lifeCycleObserver(DatabaseObserver);
// Register with custom name
app.lifeCycleObserver(DatabaseObserver, 'db-observer');Register interceptors for aspect-oriented programming and cross-cutting concerns.
/**
* Register an interceptor
*/
interceptor(
interceptor: Interceptor | Constructor<Provider<Interceptor>>,
nameOrOptions?: string | InterceptorBindingOptions
): Binding<Interceptor | Constructor<Provider<Interceptor>>>;Usage Examples:
import { Application, Interceptor, InterceptorBindingOptions } from "@loopback/core";
const loggingInterceptor: Interceptor = async (context, next) => {
console.log(`Calling method: ${context.methodName}`);
const result = await next();
console.log(`Method completed: ${context.methodName}`);
return result;
};
const app = new Application();
// Register interceptor function
app.interceptor(loggingInterceptor, 'logging');
// Register with options
app.interceptor(loggingInterceptor, {
name: 'request-logger',
global: true,
group: 'logging'
});Set and manage application metadata from package.json or other sources.
/**
* Set application metadata. @loopback/boot calls this method to populate
* the metadata from package.json.
*/
setMetadata(metadata: ApplicationMetadata): void;Usage Examples:
import { Application, ApplicationMetadata } from "@loopback/core";
const app = new Application();
const metadata: ApplicationMetadata = {
name: 'my-service',
version: '1.0.0',
description: 'A sample LoopBack application'
};
app.setMetadata(metadata);interface ApplicationConfig {
/** Name of the application context */
name?: string;
/** Configuration for signals that shut down the application */
shutdown?: ShutdownOptions;
/** Other properties */
[prop: string]: any;
}
interface ShutdownOptions {
/** An array of signals to be trapped for graceful shutdown */
signals?: NodeJS.Signals[];
/** Period in milliseconds to wait for the grace shutdown to finish */
gracePeriod?: number;
}
interface ApplicationMetadata extends JSONObject {
name: string;
version: string;
description: string;
}
type ControllerClass<T = any> = Constructor<T>;
type ServiceOrProviderClass<T = any> =
| Constructor<T | Provider<T>>
| DynamicValueProviderClass<T>;
interface Server extends LifeCycleObserver {
/** Tells whether the server is listening for connections or not */
readonly listening: boolean;
}