Modules

Organize your application into cohesive, composable blocks.

Modules group related controllers and providers into cohesive units. Every MiiaJS application has at least one root module.

Defining a module

import { Module } from '@miiajs/core'

@Module({
  controllers: [UserController],
  providers: [UserService],
})
class UserModule {}

Module options

OptionTypeDescription
controllersConstructor[]Controllers to register
providersProviderDefinition[]Services and other providers
imports(Constructor | ConfiguredModule)[]Other modules to import
prefixstringPath prefix for all controllers

Composing modules

Import modules to compose your application:

@Module({
  controllers: [UserController],
  providers: [UserService],
})
class UserModule {}

@Module({
  controllers: [PostController],
  providers: [PostService],
})
class PostModule {}

@Module({
  imports: [UserModule, PostModule],
  controllers: [HealthController],
  prefix: '/api',
})
class AppModule {}

The prefix option prepends a path to all routes in the module and its imported modules:

/api
  /users    (from UserModule)
  /posts    (from PostModule)
  /health   (from AppModule)

Dynamic modules

Some modules need runtime configuration. Use the ConfiguredModule pattern:

class DatabaseModule {
  static configure(url: string): ConfiguredModule {
    return {
      module: DatabaseModule,
      providers: [
        {
          token: 'DB_URL',
          factory: () => url,
        },
        DatabaseService,
      ],
    }
  }
}

Use it in imports:

@Module({
  imports: [
    DatabaseModule.configure(process.env.DATABASE_URL),
  ],
})
class AppModule {}

Many MiiaJS packages use this pattern — ConfigModule.configure() (from @miiajs/config), DrizzleModule.configure(), JwtModule.configure(), PaprModule.configure().

Registering with the app

Register your root module with the Miia instance:

const app = new Miia()
  .register(AppModule)

await app.listen(3000)

You can register multiple modules:

const app = new Miia()
  .register(AppModule, FeatureModule)

Module loading order

  1. RegistrationModuleLoader processes all modules recursively, registering providers in the DI container
  2. Route resolution — Controllers are instantiated and routes are compiled into the router