Skip to main content
A module is the unit of composition in Talos: a single ModuleType object that declares what a domain owns. You don’t write glue code to wire controllers, entities, or jobs together. You list the classes in the appropriate array, and the framework resolves and wires each one through the dependency injection container. Composing a module is the act of collecting a domain’s artifacts in one place; registering it is the act of exposing them to the running app.

How it works

A ModuleType from @talosjs/module has one array per artifact kind. Listing a class in an array is the declaration. The framework reads the module, registers each class with the container, and applies its decorators (routing for controllers, @decorator.middleware() for middleware, and so on).
Every class you list is resolved through the DI container. That is what makes a bare array entry enough: the container constructs the class, injects its dependencies, and the framework reads its decorators to plug it into routing, the scheduler, or the event bus.

Composing a module

Build a module up one array at a time. Each array maps to a kind of artifact the domain owns, nothing more.

controllers

Both HTTP and WebSocket controllers go in controllers. The framework registers each one’s routes from its @Route.* decorators.

entities

List the TypeORM-backed entities the domain persists. Registering them here makes them part of the data source, so repositories and migrations can find them.

middlewares

Middleware that intercepts the domain’s requests or socket connections goes here. The framework registers each via its @decorator.middleware().

cronJobs

Scheduled work the domain runs on a timer belongs in cronJobs. Each job is registered with the scheduler from its cron expression.

events

Pub/sub handlers the domain reacts to (or emits) go in events. Each is registered as a subscriber on the event bus.
The result is a complete vertical slice: one object that declares every artifact the order domain owns, with no wiring code in between.

Registering a module

Composing a module declares its artifacts; registering it exposes them to the running app. A module is registered into a destination module. The app destination registers a new module into both AppModule and SharedModule, wiring that module:create handles for you. Once registered, the app has access to every artifact the registered modules declare.
From there, resolution flows through the DI container. The app reads each registered module, registers every listed class with the container, and the framework applies the decorators. Controllers join the router, middleware joins the pipeline, cron jobs join the scheduler, events join the bus, and entities join the data source. Nothing is resolved until it is declared in a module that has been registered into the app.

Drawing module boundaries

A module is a vertical slice, so keep one domain per module: the order domain in OrderModule, the auth domain in AuthModule, with no unrelated concerns mixed into a single object. Every array entry is a declaration of ownership. If a class belongs to another domain, declare it in that domain’s module rather than duplicating it into yours. When two domains need the same artifact, declare it once in the shared module instead of reaching across module boundaries; SharedModule is the seam for cross-cutting code. And let the tooling do the wiring. The :create commands auto-register artifacts in the right array, and registering a module through app exposes it, so there is rarely a reason to hand-edit AppModule outside the generated flow.

Learn more

  • Module overview: what a module is and why Talos composes by domain.
  • Module structure: how a module’s files are laid out on disk.
  • Dependency injection: how the container resolves and wires declared artifacts.
  • Routing: how @Route.* decorators turn controllers into routes.
  • Events: writing the pub/sub handlers you list in events.
  • WebSockets: socket controllers and middleware that share the controllers and middlewares arrays.