@dunx/core
DI container, modules, lifecycle and the injectable Logger contract for the dunx framework
The dependency injection container, modules, lifecycle, configuration, and the
Logger and RequestContext contracts for
dunx.
No dependencies. The other dunx packages can inject a Logger without
installing a logging library.
Usage
Constructor injection needs no decorators:
import { AppFactory, Module } from '@dunx/core';
export class UsersService {
constructor(private readonly repo: UsersRepository) {}
}
@Module({
providers: [UsersRepository, UsersService],
exports: [UsersService], // absent means nothing is exported
})
export class UsersModule {}
const app = await AppFactory.create(AppModule);You do not need @Injectable, @Inject, reflect-metadata or
experimentalDecorators. @dunx/transform reads each constructor's parameter
types when the file loads. Turn it on in bunfig.toml, once for the app and once
for tests:
preload = ["@dunx/transform/preload"]
[test]
preload = ["@dunx/transform/preload"]What is here
| Area | What it covers | Guide |
|---|---|---|
| Providers | Constructor injection, provide(), token(), inject() | Providers |
| Modules | Scoping, imports, exports, global, forRoot | Modules |
| Lifecycle | onInit, onBeforeShutdown, onShutdown, signal handlers | Lifecycle |
| Configuration | ConfigModule.forRoot, a validate function or a schema | Configuration |
| Logging | The Logger contract and ConsoleLogger | Logging |
| Events | EventBus, AppEvent, @OnEvent, EventRegistry | Events |
| Stats | Durations, Counter, Gauge, RuntimeStats, EventLoopLag | Metrics |
| Resilience | ResiliencePolicy, timeout, retry, backoff, jitter, fallback | Resilience |
| Tracing | The Tracer contract, NoopTracer, and OtelModule on /otel | Tracing |
Subpaths
| Subpath | Contains |
|---|---|
@dunx/core | Everything above. Never imports @opentelemetry/api |
@dunx/core/otel | OtelModule and OtelTracer, on the optional peer @opentelemetry/api |
bun add @opentelemetry/api # only for @dunx/core/otel, ^1.4.0@opentelemetry/api is a peer dependency so that your SDK and dunx use the
same copy. With two copies installed, spans can go missing without an error.
dunx does not include an SDK or an exporter: register your own before calling
create.
Notes
-
Each module is its own scope. A module can use what it declares and what the modules it imports export. List what other modules may use in
exports; leaveexportsout and nothing is shared.global: truemakes a module's exports available everywhere. -
If a constructor parameter's type does not exist at runtime (an interface, a primitive, a union or a type-only import), boot fails with an error naming that parameter. You never get a silent
undefined. A parameter with a default value keeps its default. -
Logger,RequestContextandTracercan always be injected. The defaults areConsoleLogger,AsyncRequestContext(onAsyncLocalStorage) andNoopTracer, and a module that binds one replaces the default.@dunx/httprelies on this to log requests in an app with no logging module. -
ConsoleLoggercollectsinfoand lower into one write per event-loop turn.warnand higher are written at once, along with anything waiting before them. -
The stats classes use only
node:perf_hooksandprocess, so the package still has no dependencies. -
Durationsfixes four problems with Node's native histogram:Native histogram Durationsrecord(0)throwsERR_OUT_OF_RANGEA value under 1 is recorded as 1 An empty histogram reports min9223372036854776000,meanNaNAn empty snapshot is { count: 0 }percentilesis aMapofbigint, which serialises to{}percentile(n)returns a numbermeancosts 42.2 usNo mean