Skip to main content

Modules

Overview

A module is a class annotated with a @Module() decorator. The @Module() decorator provides metadata that organizes the application structure. Modules encapsulate related functionality and follow the NestJS module pattern.

Module Structure

A typical module in MBC CQRS Serverless includes:

import { Module } from '@nestjs/common';
import { CommandModule } from '@mbc-cqrs-serverless/core';

import { CatController } from './cat.controller';
import { CatService } from './cat.service';
import { CatDataSyncRdsHandler } from './handler/cat-rds.handler';

@Module({
imports: [
CommandModule.register({
tableName: 'cat',
dataSyncHandlers: [CatDataSyncRdsHandler],
}),
],
controllers: [CatController],
providers: [CatService],
exports: [CatService],
})
export class CatModule {}

Module Components

ComponentDescription
importsList of imported modules that export providers used in this module
controllersControllers that handle HTTP requests
providersServices and other providers available for injection
exportsProviders that should be available in modules that import this module

Framework Modules

MBC CQRS Serverless provides several ready-to-use modules:

Core Modules

ModulePackagePurpose
CommandModule@mbc-cqrs-serverless/coreCQRS command handling and data sync
SequencesModule@mbc-cqrs-serverless/sequenceSequential ID generation
TenantModule@mbc-cqrs-serverless/tenantMulti-tenant management

Feature Modules

ModulePackagePurpose
TaskModule@mbc-cqrs-serverless/taskAsync task execution with Step Functions
MasterModule@mbc-cqrs-serverless/masterMaster data and settings management
ImportModule@mbc-cqrs-serverless/importCSV/API data import
DirectoryStorageModule@mbc-cqrs-serverless/directoryFile and folder management with S3
SurveyTemplateModule@mbc-cqrs-serverless/survey-templateSurvey template management

Support Modules

ModulePackagePurpose
QueueModule@mbc-cqrs-serverless/coreSNS publish and SQS send/receive messaging
NotificationModule@mbc-cqrs-serverless/coreEmail via SES and real-time WebSocket notifications via AppSync
SettingModule@mbc-cqrs-serverless/ui-settingUser interface settings storage

Dynamic Module Registration

Most framework modules are dynamic modules that accept configuration:

CommandModule

CommandModule.register({
tableName: 'cat',
dataSyncHandlers: [CatDataSyncRdsHandler],
skipError: false,
disableDefaultHandler: false,
})
OptionTypeDefaultDescription
tableNamestringRequiredDynamoDB table name (without postfix)
dataSyncHandlersType[][]Data sync handler classes
skipErrorbooleanfalseReserved for future use (not yet implemented)
disableDefaultHandlerbooleanfalseDisable default DynamoDB data sync handler

SequencesModule

SequencesModule.register({
enableController: true, // Enable built-in sequence REST endpoints
})
OptionTypeDefaultDescription
enableControllerbooleanfalseEnable the built-in sequence generation endpoints

TenantModule

The TenantModule provides multi-tenant management. It can expose REST endpoints for creating and updating tenants and their group configurations.

import { TenantModule } from '@mbc-cqrs-serverless/tenant';

TenantModule.register({
enableController: true, // Enable built-in tenant REST endpoints
dataSyncHandlers: [TenantRdsSyncHandler], // Optional: Data sync handlers for RDS synchronization
})
OptionTypeDefaultDescription
enableControllerbooleanfalseEnable the built-in TenantController endpoints
dataSyncHandlersType[][]Data sync handler classes

See Tenant for the full API reference.

MasterModule

MasterModule.register({
enableController: true,
prismaService: PrismaService,
})
MasterModule Configuration Note

When enableController: true, the prismaService parameter is required. You must provide your application's PrismaService class. The framework will throw an error if prismaService is not provided when controllers are enabled.

TaskModule

TaskModule handles asynchronous task execution using AWS Step Functions. It requires a custom event factory that implements ITaskQueueEventFactory.

import { TaskModule } from '@mbc-cqrs-serverless/task';
import { MyTaskQueueEventFactory } from './my-task-queue-event.factory';

TaskModule.register({
taskQueueEventFactory: MyTaskQueueEventFactory,
enableController: true,
})
OptionTypeDefaultDescription
taskQueueEventFactoryType<ITaskQueueEventFactory>RequiredFactory class for transforming task queue events
enableControllerbooleanfalseEnable built-in task REST endpoints

The taskQueueEventFactory must implement the ITaskQueueEventFactory interface. Both methods are optional - implement only what you need:

import { ITaskQueueEventFactory, TaskQueueEvent, StepFunctionTaskEvent } from '@mbc-cqrs-serverless/task';
import { IEvent } from '@mbc-cqrs-serverless/core';
import { MyTaskEvent } from './my-task.event';
import { MyStepFunctionTaskEvent } from './my-sfn-task.event';

export class MyTaskQueueEventFactory implements ITaskQueueEventFactory {
// Optional: Transform SQS task queue events into domain events
async transformTask(event: TaskQueueEvent): Promise<IEvent[]> {
// Create domain-specific events from task queue events
return [new MyTaskEvent().fromSqsRecord(event)];
}

// Optional: Transform Step Function task events into domain events
async transformStepFunctionTask(event: StepFunctionTaskEvent): Promise<IEvent[]> {
// Check taskKey.sk to determine which event type to create
if (event.taskKey.sk.startsWith('MY_TASK')) {
return [new MyStepFunctionTaskEvent(event)];
}
return [];
}
}

ImportModule

The ImportModule provides CSV and API data import functionality. It requires defining import profiles that specify how data should be imported and processed for each entity type.

import { ImportModule } from '@mbc-cqrs-serverless/import';
import { PolicyImportStrategy } from './strategies/policy-import.strategy';
import { PolicyProcessStrategy } from './strategies/policy-process.strategy';
import { PolicyModule } from './policy.module';

@Module({
imports: [
ImportModule.register({
profiles: [
{
tableName: 'policy',
importStrategy: PolicyImportStrategy,
processStrategy: PolicyProcessStrategy,
},
],
imports: [PolicyModule], // Modules that export providers needed by strategies
enableController: true,
}),
],
})
export class AppModule {}
OptionTypeDefaultDescription
profilesImportEntityProfile[]RequiredArray of import profiles for each entity type
importsModuleMetadata['imports'][]Modules that export providers needed by strategy classes
enableControllerbooleanfalseEnable built-in /imports, /imports/csv, and /imports/zip endpoints

Each ImportEntityProfile requires:

PropertyTypeDescription
tableNamestringUnique identifier for the data type (e.g., 'policy', 'user')
importStrategyType<IImportStrategy>Class implementing import logic (transform & validate)
processStrategyType<IProcessStrategy>Class implementing business processing logic (compare & map)

DirectoryStorageModule

The DirectoryStorageModule provides S3-backed file and folder management with permissions, version history, and presigned URL generation.

import { DirectoryStorageModule } from '@mbc-cqrs-serverless/directory';
import { PrismaService } from './prisma.service';

DirectoryStorageModule.register({
enableController: true,
prismaService: PrismaService,
dataSyncHandlers: [],
})
OptionTypeDefaultDescription
enableControllerbooleanfalseEnable built-in directory REST endpoints
prismaServiceType<PrismaService>Required when enableController is trueApplication PrismaService class
dataSyncHandlersType[][]Data sync handler classes

SurveyTemplateModule

The SurveyTemplateModule provides survey template management with support for multiple question types including text, radio, checkbox, and rating questions.

import { SurveyTemplateModule } from '@mbc-cqrs-serverless/survey-template';
import { PrismaService } from './prisma.service';

SurveyTemplateModule.register({
enableController: true,
prismaService: PrismaService,
})
OptionTypeDefaultDescription
enableControllerbooleanfalseEnable built-in survey template REST endpoints
prismaServiceType<PrismaService>Required when enableController is trueApplication PrismaService class

SettingModule

The SettingModule manages user interface settings. It can optionally expose REST endpoints for managing settings.

import { SettingModule } from '@mbc-cqrs-serverless/ui-setting';

@Module({
imports: [
SettingModule.register({
enableSettingController: true,
enableDataController: true,
}),
],
})
export class AppModule {}
OptionTypeDefaultDescription
enableSettingControllerbooleanfalseEnable the setting controller for UI settings management
enableDataControllerbooleanfalseEnable the data setting controller for data-related settings

NotificationModule (Static)

The NotificationModule is a static (not dynamic) module that provides email notifications via SES and real-time updates via AppSync. It is automatically registered as a global module, so you only need to import it once in your AppModule.

import { NotificationModule } from '@mbc-cqrs-serverless/core';

@Module({
imports: [
NotificationModule, // No configuration needed - static module
],
})
export class AppModule {}

This module exports:

  • EmailService - Send emails via Amazon SES
  • AppSyncService - Send real-time notifications via AppSync (GraphQL Subscriptions)
  • AppSyncEventsService - Send real-time notifications via AppSync Events API (opt-in, added in v1.3.0) → Notification Module

Creating Custom Modules

Step 1: Create Module File

// src/order/order.module.ts
import { Module } from '@nestjs/common';
import { CommandModule } from '@mbc-cqrs-serverless/core';
import { SequencesModule } from '@mbc-cqrs-serverless/sequence';

import { OrderController } from './order.controller';
import { OrderService } from './order.service';
import { OrderDataSyncHandler } from './handlers/order-data-sync.handler';

@Module({
imports: [
CommandModule.register({
tableName: 'order',
dataSyncHandlers: [OrderDataSyncHandler],
}),
SequencesModule.register({
enableController: false,
}),
],
controllers: [OrderController],
providers: [OrderService],
exports: [OrderService],
})
export class OrderModule {}

Step 2: Register in AppModule

// src/app.module.ts
import { Module } from '@nestjs/common';
import { OrderModule } from './order/order.module';

@Module({
imports: [OrderModule],
})
export class AppModule {}

Best Practices

  1. One module per entity: Create a dedicated module for each business entity
  2. Export services, not controllers: Only export providers that other modules need
  3. Use forRoot for global modules: Register global configuration once in AppModule
  4. Keep modules focused: Each module should have a single responsibility