CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nestjs--mongoose

NestJS module that provides seamless integration between NestJS and Mongoose ODM for MongoDB database operations

80

1.02x
Quality

Pending

Does it follow best practices?

Impact

80%

1.02x

Average score across 10 eval scenarios

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

dependency-injection.mddocs/

Dependency Injection

Decorators for injecting Mongoose models and connections into NestJS services and controllers. The dependency injection system integrates seamlessly with NestJS's DI container to provide type-safe model and connection injection.

Capabilities

@InjectModel Decorator

Injects a Mongoose model into constructor parameters for use in services and controllers.

/**
 * Parameter decorator that injects a Mongoose model
 * @param model - Model name to inject
 * @param connectionName - Optional connection name for multi-database setup
 * @returns Parameter decorator function
 */
function InjectModel(model: string, connectionName?: string): ParameterDecorator;

Usage Examples:

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './schemas/user.schema';

// Basic model injection
@Injectable()
export class UserService {
  constructor(@InjectModel(User.name) private userModel: Model<User>) {}

  async create(createUserDto: any): Promise<User> {
    const createdUser = new this.userModel(createUserDto);
    return createdUser.save();
  }

  async findAll(): Promise<User[]> {
    return this.userModel.find().exec();
  }

  async findById(id: string): Promise<User> {
    return this.userModel.findById(id).exec();
  }

  async update(id: string, updateUserDto: any): Promise<User> {
    return this.userModel.findByIdAndUpdate(id, updateUserDto, { new: true }).exec();
  }

  async delete(id: string): Promise<User> {
    return this.userModel.findByIdAndDelete(id).exec();
  }
}

// Multi-database model injection
@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name, 'users-db') private userModel: Model<User>,
    @InjectModel(Profile.name, 'profiles-db') private profileModel: Model<Profile>,
  ) {}

  async createUserWithProfile(userData: any, profileData: any): Promise<{ user: User; profile: Profile }> {
    const user = await new this.userModel(userData).save();
    const profile = await new this.profileModel({ ...profileData, userId: user._id }).save();
    return { user, profile };
  }
}

// Multiple models in single service
@Injectable()
export class BlogService {
  constructor(
    @InjectModel(Post.name) private postModel: Model<Post>,
    @InjectModel(Comment.name) private commentModel: Model<Comment>,
    @InjectModel(User.name) private userModel: Model<User>,
  ) {}

  async createPostWithAuthor(postData: any, authorId: string): Promise<Post> {
    const author = await this.userModel.findById(authorId);
    if (!author) {
      throw new Error('Author not found');
    }
    
    const post = new this.postModel({ ...postData, author: authorId });
    return post.save();
  }

  async addComment(postId: string, commentData: any): Promise<Comment> {
    const post = await this.postModel.findById(postId);
    if (!post) {
      throw new Error('Post not found');
    }

    const comment = new this.commentModel({ ...commentData, post: postId });
    return comment.save();
  }
}

@InjectConnection Decorator

Injects a Mongoose connection instance for advanced database operations and transaction management.

/**
 * Parameter decorator that injects a Mongoose connection
 * @param name - Optional connection name for multi-database setup
 * @returns Parameter decorator function
 */
function InjectConnection(name?: string): ParameterDecorator;

Usage Examples:

import { Injectable } from '@nestjs/common';
import { InjectConnection, InjectModel } from '@nestjs/mongoose';
import { Connection, Model } from 'mongoose';
import { User } from './schemas/user.schema';
import { Order } from './schemas/order.schema';

// Basic connection injection
@Injectable()
export class DatabaseService {
  constructor(@InjectConnection() private connection: Connection) {}

  async getDatabaseStats(): Promise<any> {
    const stats = await this.connection.db.stats();
    return {
      database: this.connection.name,
      collections: stats.collections,
      dataSize: stats.dataSize,
      indexSize: stats.indexSize,
    };
  }

  async createIndexes(): Promise<void> {
    const collections = await this.connection.db.listCollections().toArray();
    for (const collection of collections) {
      await this.connection.collection(collection.name).createIndex({ createdAt: -1 });
    }
  }
}

// Named connection injection
@Injectable()
export class MultiDbService {
  constructor(
    @InjectConnection('users-db') private usersConnection: Connection,
    @InjectConnection('orders-db') private ordersConnection: Connection,
  ) {}

  async syncUserData(userId: string): Promise<void> {
    const session = await this.usersConnection.startSession();
    try {
      await session.withTransaction(async () => {
        // Perform operations within transaction
        const user = await this.usersConnection.collection('users').findOne({ _id: userId });
        if (user) {
          await this.usersConnection.collection('user_cache').replaceOne(
            { userId },
            { ...user, lastSync: new Date() },
            { upsert: true }
          );
        }
      });
    } finally {
      await session.endSession();
    }
  }
}

// Transaction management with connection and models
@Injectable()
export class TransactionService {
  constructor(
    @InjectConnection() private connection: Connection,
    @InjectModel(User.name) private userModel: Model<User>,
    @InjectModel(Order.name) private orderModel: Model<Order>,
  ) {}

  async createUserAndOrder(userData: any, orderData: any): Promise<{ user: User; order: Order }> {
    const session = await this.connection.startSession();
    
    try {
      const result = await session.withTransaction(async () => {
        // Create user within transaction
        const user = new this.userModel(userData);
        await user.save({ session });

        // Create order within same transaction
        const order = new this.orderModel({ ...orderData, userId: user._id });
        await order.save({ session });

        return { user, order };
      });

      return result;
    } finally {
      await session.endSession();
    }
  }
}

Utility Functions

getModelToken

Generates the dependency injection token used for model injection.

/**
 * Generates dependency injection token for a model
 * @param model - Model name
 * @param connectionName - Optional connection name
 * @returns DI token string
 */
function getModelToken(model: string, connectionName?: string): string;

Usage Examples:

import { getModelToken } from '@nestjs/mongoose';

// Get token for default connection
const userToken = getModelToken('User');
// Returns: 'UserModel'

// Get token for named connection
const userTokenWithConnection = getModelToken('User', 'users-db');
// Returns: 'users-db/UserModel'

// Use in custom providers
const providers = [
  {
    provide: 'CUSTOM_USER_SERVICE',
    useFactory: (userModel: Model<User>) => {
      return new CustomUserService(userModel);
    },
    inject: [getModelToken(User.name)],
  },
];

getConnectionToken

Generates the dependency injection token used for connection injection.

/**
 * Generates dependency injection token for a connection
 * @param name - Optional connection name
 * @returns DI token string
 */
function getConnectionToken(name?: string): string;

Usage Examples:

import { getConnectionToken } from '@nestjs/mongoose';

// Get token for default connection
const defaultConnectionToken = getConnectionToken();
// Returns: 'DatabaseConnection'

// Get token for named connection
const namedConnectionToken = getConnectionToken('users-db');
// Returns: 'users-db'

// Use in custom providers
const providers = [
  {
    provide: 'DATABASE_HEALTH_CHECK',
    useFactory: (connection: Connection) => {
      return new DatabaseHealthCheck(connection);
    },
    inject: [getConnectionToken()],
  },
];

Advanced Integration Patterns

Custom Providers with Tokens

import { Module, Provider } from '@nestjs/common';
import { getModelToken, getConnectionToken } from '@nestjs/mongoose';

const customProviders: Provider[] = [
  {
    provide: 'USER_REPOSITORY',
    useFactory: (userModel: Model<User>) => {
      return new UserRepository(userModel);
    },
    inject: [getModelToken(User.name)],
  },
  {
    provide: 'DATABASE_MANAGER',
    useFactory: (connection: Connection) => {
      return new DatabaseManager(connection);
    },
    inject: [getConnectionToken()],
  },
];

@Module({
  providers: [...customProviders],
  exports: ['USER_REPOSITORY', 'DATABASE_MANAGER'],
})
export class CustomModule {}

Testing with Injection Tokens

import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from '@nestjs/mongoose';

describe('UserService', () => {
  let service: UserService;
  let model: Model<User>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserService,
        {
          provide: getModelToken(User.name),
          useValue: {
            find: jest.fn(),
            findById: jest.fn(),
            create: jest.fn(),
            save: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get<UserService>(UserService);
    model = module.get<Model<User>>(getModelToken(User.name));
  });

  it('should find all users', async () => {
    const users = [{ name: 'Test User' }];
    jest.spyOn(model, 'find').mockReturnValue({
      exec: jest.fn().mockResolvedValue(users),
    } as any);

    const result = await service.findAll();
    expect(result).toEqual(users);
  });
});

docs

dependency-injection.md

index.md

module-configuration.md

schema-definition.md

schema-factories.md

utility-functions.md

validation-pipes.md

tile.json