Modules are the primary way to organize an nestelia application. Each module encapsulates a set of controllers, providers, and imports.
Defining a Module
Use the @Module() decorator to declare a module:
typescript
import { Module } from "nestelia";
@Module({
controllers: [UserController],
providers: [UserService],
})
class UserModule {}Module Options
typescript
interface ModuleOptions {
controllers?: Type[]; // Route handlers
providers?: Provider[]; // Injectable services
imports?: any[]; // Other modules to import
exports?: ProviderToken[]; // Providers available to importing modules
middlewares?: Middleware[]; // Class-based or functional middleware
children?: (() => Promise<any>)[]; // Child modules
prefix?: string; // Route prefix for all controllers
}Importing Modules
Modules can import other modules to access their exported providers:
typescript
@Module({
providers: [DatabaseService],
exports: [DatabaseService],
})
class DatabaseModule {}
@Module({
imports: [DatabaseModule],
controllers: [UserController],
providers: [UserService],
})
class UserModule {}UserService can now inject DatabaseService because DatabaseModule exports it.
Root Module
Every application has a root module passed to createElysiaApplication():
typescript
@Module({
imports: [UserModule, AuthModule, DatabaseModule],
})
class AppModule {}
const app = await createElysiaApplication(AppModule);Module Prefix
Apply a route prefix to all controllers in a module:
typescript
@Module({
controllers: [UserController], // routes become /api/v1/users/...
prefix: "/api/v1",
})
class ApiModule {}Global Modules
Mark a module as global so its providers are available everywhere without importing:
typescript
import { Global, Module } from "nestelia";
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
class ConfigModule {}Dynamic Modules
Modules can expose static configuration methods like forRoot() and forRootAsync():
typescript
@Module({})
class ConfigModule {
static forRoot(options: ConfigOptions): DynamicModule {
return {
module: ConfigModule,
providers: [
{ provide: "CONFIG_OPTIONS", useValue: options },
ConfigService,
],
exports: [ConfigService],
};
}
}
// Usage
@Module({
imports: [ConfigModule.forRoot({ path: ".env" })],
})
class AppModule {}How It Works
Under the hood, @Module() creates an Elysia plugin. When createElysiaApplication() is called:
- The DI container registers all providers from the module
- Controllers are instantiated with their dependencies resolved
- HTTP routes are registered on the Elysia instance
- Lifecycle hooks are invoked in order