This file provides AI coding agents with essential context for working on the nestjs-dynamoose project.
nestjs-dynamoose is a NestJS module that integrates Dynamoose (a DynamoDB ODM) with NestJS's dependency injection system. It provides decorators, providers, and utilities to seamlessly use DynamoDB models in NestJS applications.
Key Purpose: Bridge the gap between Dynamoose's ODM functionality and NestJS's module/DI architecture.
The project follows NestJS's standard dynamic module pattern with global and feature modules:
DynamooseCoreModule(Global): Handles Dynamoose initialization, AWS configuration, and global setupDynamooseModule(Feature): Provides model registration via static methods:forRoot(options)/forRootAsync(options)- Global configurationforFeature(models)/forFeatureAsync(factories)- Model registration per feature module
Models are injected using a token-based system:
@InjectModel('User')
private userModel: Model<User, UserKey>The getModelToken(name) utility in lib/common/dynamoose.utils.ts creates consistent tokens for model providers.
| File | Purpose |
|---|---|
lib/dynamoose.module.ts |
Main module with static registration methods |
lib/dynamoose-core.module.ts |
Global module handling Dynamoose initialization |
lib/dynamoose.providers.ts |
Creates model providers with proper DI |
lib/common/dynamoose.decorators.ts |
Exports @InjectModel() decorator |
lib/common/dynamoose.utils.ts |
Token generation utilities |
lib/interfaces/ |
TypeScript interfaces for module options, models, transactions |
npm run build # Compile TypeScript (lib/ → dist/)
npm run lint # ESLint with Prettier integration
npm run format # Prettier formatting for lib/**/*.ts- Source:
lib/directory (NOTsrc/) - Output:
dist/directory - Entry point:
index.tsexports./dist - TypeScript: CommonJS modules, decorators enabled, strict mode
- Target: ES2021, Node.js compatible
- GitHub Actions: Node.js 22.17.1
- Steps:
npm ci→npm run lint→npm run build - Pre-commit hooks:
lint-stagedruns Prettier on*.tsfilescommitlintenforces Angular commit conventions
Follow Angular conventions:
<type>(<scope>): <subject>
Examples:
- feature(core): add support for Dynamoose v4
- bugfix(providers): fix async model factory injection
- docs(readme): improve transaction example
Types: build, ci, docs, feature, bugfix, perf, refactor, style, test
lib/
├── common/ # Decorators & utilities
├── interfaces/ # TypeScript interfaces with barrel exports
├── dynamoose.module.ts # Main module
├── dynamoose-core.module.ts
├── dynamoose.providers.ts
├── dynamoose.constants.ts
└── index.ts # Public API
Interface Segregation: Separate key interfaces from document interfaces
// Key interface (hash/range keys only)
export interface UserKey {
id: string;
}
// Document interface (all attributes)
export interface User extends UserKey {
name: string;
email?: string;
}Type Safety with Dynamoose:
- Extensive use of
anytypes for Dynamoose compatibility - ESLint rules disabled:
@typescript-eslint/no-unsafe-*,@typescript-eslint/no-explicit-any - This is intentional due to Dynamoose's dynamic nature
Synchronous:
DynamooseModule.forFeature([{
name: 'User',
schema: UserSchema,
options: { tableName: 'user' }
}])Async with DI:
DynamooseModule.forFeatureAsync([{
name: 'User',
useFactory: (_, configService: ConfigService) => ({
schema: UserSchema,
options: { tableName: configService.get('USER_TABLE_NAME') }
}),
inject: [ConfigService]
}])useFactory is reserved (ignore with _,)
The TransactionSupport abstract class provides transaction capabilities:
@Injectable()
export class UserService extends TransactionSupport {
constructor(
@InjectModel('User') private userModel: Model<User, UserKey>,
@InjectModel('Account') private accountModel: Model<Account, AccountKey>
) {
super();
}
async createUserWithAccount(user: User, account: Account) {
await this.transaction([
this.userModel.transaction.create(user),
this.accountModel.transaction.create(account)
]);
}
}- dynamoose: ^3.2.0 || ^4.0.0 - DynamoDB ODM
- @nestjs/common & @nestjs/core: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
- @aws-sdk/client-dynamodb: ^3.0.0
- rxjs: ^6.0.0 || ^7.0.0
- reflect-metadata: ^0.1.13 || ^0.2.0
- Minimal dev dependencies (only build/lint tooling)
- No test framework (library focused, consumers test integration)
- ESLint with Prettier integration
- TypeScript 5.9+
- Global Config:
DynamooseModule.forRoot(options)inAppModule - Model Registration:
DynamooseModule.forFeature([...])in feature modules - Service Injection:
@InjectModel('ModelName')in service constructors
interface DynamooseModuleOptions {
aws?: {
accessKeyId?: string;
secretAccessKey?: string;
region?: string;
};
local?: boolean | string; // Local DynamoDB endpoint
ddb?: DynamoDB; // Custom DynamoDB instance
table?: TableOptionsOptional; // Global table defaults
logger?: boolean | LoggerService; // Logging configuration
}Serializers: Define custom serializers per model
DynamooseModule.forFeature([{
name: 'User',
schema: UserSchema,
serializers: {
frontend: { exclude: ['password', 'internalStatus'] }
}
}])Then use: user.serialize('frontend')
- No test files in repository - This is a library focused on integration
- TypeScript config excludes
**/*.spec.ts - Consumers should integration test in their applications
- Example project: aws-nestjs-starter
- Update TypeScript interfaces in
lib/interfaces/ - Modify providers or module as needed
- Update
index.tsto export new public API - Update README.md with usage examples
- Run
npm run buildandnpm run lint - Follow commit message conventions
- Update peer dependency range in
package.json - Test with both min and max supported versions
- Update README.md compatibility notes
- Check for breaking changes in Dynamoose changelog
⚠️ Reserved factory parameter: First param inuseFactoryis reserved, always ignore with_,⚠️ Global module:DynamooseCoreModuleis@Global()- models available everywhere after registration⚠️ Async initialization: Dynamoose initialization happens via provider factory, not module constructor⚠️ Token naming: Model tokens usegetModelToken(name)- must match exactly for injection
- Documentation: Dynamoose Docs
- Example Project: aws-nestjs-starter
- Issues: Use GitHub issue templates
- Questions: Stack Overflow with tag
nestjs-dynamoose
- Update version following semantic versioning
- Run
npm run buildto ensure clean compilation - Run
npm run release(usesrelease-it) - Publish:
npm run publish:npmornpm run publish:next
- Never commit AWS credentials
- Use environment variables for sensitive configuration
- Prefer
forRootAsync()withConfigServicefor production - Use IAM roles in AWS environments (don't hardcode credentials)
- Enable logger in development, disable or use custom logger in production
Last Updated: 2025-01-30
This guide should be updated when major architectural changes occur.