| name | loopback-core |
| description | Build large-scale, extensible Node.js applications and frameworks using LoopBack 4 core patterns. Use when building TypeScript/Node.js projects that need IoC containers, dependency injection, extension point/extension patterns, interceptors, life cycle observers, or component-based architecture. Triggers on tasks involving @loopback/core, @loopback/context, Context, Binding, @inject, @injectable, @extensionPoint, @extensions, LifeCycleObserver, Interceptor, or Component patterns. Also use when the user asks about structuring large-scale Node.js projects for extensibility and composability. |
Build Large-Scale Node.js Projects with LoopBack 4 Core
LoopBack 4 core provides an IoC container and DI framework in TypeScript
designed for async-first, large-scale Node.js applications. Import from
@loopback/core (not @loopback/context). This skill covers only
@loopback/core — not REST, repositories, or other LoopBack modules.
Architecture Decision Tree
- Need to manage artifacts and their dependencies? -> Context & Bindings
(context-and-bindings.md)
- Need loose coupling between artifact construction and behavior? ->
Dependency Injection
(dependency-injection.md)
- Need a pluggable system where others can add capabilities? -> Extension
Point/Extension (extension-points.md)
- Need cross-cutting concerns (caching, logging, tracing)? -> Interceptors
(interceptors-and-observers.md)
- Need to hook into app start/stop? -> Life Cycle Observers
(interceptors-and-observers.md)
- Need runtime-configurable artifacts? -> Configuration
(configuration.md)
- Need custom decorators, parameterized classes, or advanced patterns? ->
Advanced Recipes (advanced-recipes.md)
Quick Start: Minimal Extensible Application
import {
Application,
BindingKey,
Component,
Binding,
createBindingFromClass,
extensionPoint,
extensions,
BindingTemplate,
extensionFor,
injectable,
Getter,
config,
} from '@loopback/core';
export interface Greeter {
language: string;
greet(name: string): string;
}
export const GREETER_EXTENSION_POINT_NAME = 'greeters';
export const asGreeter: BindingTemplate = binding => {
extensionFor(GREETER_EXTENSION_POINT_NAME)(binding);
binding.tag({namespace: 'greeters'});
};
@extensionPoint(GREETER_EXTENSION_POINT_NAME)
export class GreetingService {
constructor(
@extensions() private getGreeters: Getter<Greeter[]>,
@config() public ?: {color: },
) {}
(: , : ): <> {
greeters = .();
greeter = greeters.( g. === language);
greeter ? greeter.(name) : ;
}
}
(asGreeter)
{
language = ;
() {
;
}
}
(asGreeter)
{
language = ;
() {
;
}
}
= .<>(
,
);
{
: [] = [
(, {: }),
(),
(),
];
}
{
services = [];
}
{
components = [, ];
services = [];
}
{
() {
({: {: []}});
.();
}
() {
svc = .();
.( svc.(, ));
}
}
Core Patterns Summary
| Pattern | Key APIs | When to Use |
|---|
| Context & Binding | Context, bind(), toClass(), toDynamicValue(), toProvider() | Managing artifacts and their dependencies |
| DI | @inject(), @inject.getter(), @inject.view() | Decoupling construction from behavior |
| Extension Point | @extensionPoint(), @extensions(), @extensions.list(), extensionFor(), @injectable() | Pluggable, open-ended feature sets |
| Interceptor | @injectable(asGlobalInterceptor()), Provider<Interceptor> | Cross-cutting concerns |
| Observer | @lifeCycleObserver('group'), LifeCycleObserver | Startup/shutdown hooks (group controls order) |
| Configuration | @config(), @config.view(), app.configure() | Runtime-configurable behavior |
| Component | Component, components[], services[], bindings[] | Composable packaging of artifacts |
Key Rules
- Always import from
@loopback/core, not @loopback/context
- Use
BindingKey.create<T>() for strongly-typed keys
- Extension injection:
@extensions() returns Getter<T[]> (lazy, picks up
dynamic additions); @extensions.list() returns T[] (eager, simpler when
extensions are static at startup)
- Use
@config() for artifact configuration, app.configure(key).to(value) to
set it
- Use
@injectable(bindingTemplate) to decorate extension classes — can combine
scope and extension:
@injectable({scope: BindingScope.SINGLETON}, extensionFor(POINT))
- Use
createBindingFromClass() to create bindings that respect @injectable
metadata
- Compose components hierarchically:
components[] for nesting, services[]
for auto-registration, bindings[] for custom bindings
- Use
BindingScope.SINGLETON for shared stateful services
- Use
CoreBindings.APPLICATION_INSTANCE to inject the Application itself
- Use
ContextTags.KEY to tag bindings with a stable key:
tags: {[ContextTags.KEY]: MY_KEY}
- Lifecycle observer groups are sorted alphabetically — use numbered prefixes
(e.g.,
'03-setup', '10-app') to control startup order
References
- Context & Bindings:
references/context-and-bindings.md —
creating contexts, binding types, scopes, finding bindings, context hierarchy,
views, components
- Dependency Injection:
references/dependency-injection.md —
constructor/property/method injection, getters, views, custom decorators,
custom injectors
- Extension Points:
references/extension-points.md — defining
contracts, extension point classes, implementing/registering extensions,
configuration
- Interceptors & Observers:
references/interceptors-and-observers.md
— global interceptors, interceptor proxies, life cycle observers, dynamic
config via ContextView
- Configuration: references/configuration.md
—
@config(), @config.view(), dynamic config, custom resolvers, sync vs
async
- Advanced Recipes:
references/advanced-recipes.md — custom
decorators, custom injectors, parameterized class factories, application
scaffolding