or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dependency-injection.mdindex.mdmodule-configuration.mdschema-definition.mdschema-factories.mdutility-functions.mdvalidation-pipes.md

dependency-injection.mddocs/

0

# Dependency Injection

1

2

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.

3

4

## Capabilities

5

6

### @InjectModel Decorator

7

8

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

9

10

```typescript { .api }

11

/**

12

* Parameter decorator that injects a Mongoose model

13

* @param model - Model name to inject

14

* @param connectionName - Optional connection name for multi-database setup

15

* @returns Parameter decorator function

16

*/

17

function InjectModel(model: string, connectionName?: string): ParameterDecorator;

18

```

19

20

**Usage Examples:**

21

22

```typescript

23

import { Injectable } from '@nestjs/common';

24

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

25

import { Model } from 'mongoose';

26

import { User } from './schemas/user.schema';

27

28

// Basic model injection

29

@Injectable()

30

export class UserService {

31

constructor(@InjectModel(User.name) private userModel: Model<User>) {}

32

33

async create(createUserDto: any): Promise<User> {

34

const createdUser = new this.userModel(createUserDto);

35

return createdUser.save();

36

}

37

38

async findAll(): Promise<User[]> {

39

return this.userModel.find().exec();

40

}

41

42

async findById(id: string): Promise<User> {

43

return this.userModel.findById(id).exec();

44

}

45

46

async update(id: string, updateUserDto: any): Promise<User> {

47

return this.userModel.findByIdAndUpdate(id, updateUserDto, { new: true }).exec();

48

}

49

50

async delete(id: string): Promise<User> {

51

return this.userModel.findByIdAndDelete(id).exec();

52

}

53

}

54

55

// Multi-database model injection

56

@Injectable()

57

export class UserService {

58

constructor(

59

@InjectModel(User.name, 'users-db') private userModel: Model<User>,

60

@InjectModel(Profile.name, 'profiles-db') private profileModel: Model<Profile>,

61

) {}

62

63

async createUserWithProfile(userData: any, profileData: any): Promise<{ user: User; profile: Profile }> {

64

const user = await new this.userModel(userData).save();

65

const profile = await new this.profileModel({ ...profileData, userId: user._id }).save();

66

return { user, profile };

67

}

68

}

69

70

// Multiple models in single service

71

@Injectable()

72

export class BlogService {

73

constructor(

74

@InjectModel(Post.name) private postModel: Model<Post>,

75

@InjectModel(Comment.name) private commentModel: Model<Comment>,

76

@InjectModel(User.name) private userModel: Model<User>,

77

) {}

78

79

async createPostWithAuthor(postData: any, authorId: string): Promise<Post> {

80

const author = await this.userModel.findById(authorId);

81

if (!author) {

82

throw new Error('Author not found');

83

}

84

85

const post = new this.postModel({ ...postData, author: authorId });

86

return post.save();

87

}

88

89

async addComment(postId: string, commentData: any): Promise<Comment> {

90

const post = await this.postModel.findById(postId);

91

if (!post) {

92

throw new Error('Post not found');

93

}

94

95

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

96

return comment.save();

97

}

98

}

99

```

100

101

### @InjectConnection Decorator

102

103

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

104

105

```typescript { .api }

106

/**

107

* Parameter decorator that injects a Mongoose connection

108

* @param name - Optional connection name for multi-database setup

109

* @returns Parameter decorator function

110

*/

111

function InjectConnection(name?: string): ParameterDecorator;

112

```

113

114

**Usage Examples:**

115

116

```typescript

117

import { Injectable } from '@nestjs/common';

118

import { InjectConnection, InjectModel } from '@nestjs/mongoose';

119

import { Connection, Model } from 'mongoose';

120

import { User } from './schemas/user.schema';

121

import { Order } from './schemas/order.schema';

122

123

// Basic connection injection

124

@Injectable()

125

export class DatabaseService {

126

constructor(@InjectConnection() private connection: Connection) {}

127

128

async getDatabaseStats(): Promise<any> {

129

const stats = await this.connection.db.stats();

130

return {

131

database: this.connection.name,

132

collections: stats.collections,

133

dataSize: stats.dataSize,

134

indexSize: stats.indexSize,

135

};

136

}

137

138

async createIndexes(): Promise<void> {

139

const collections = await this.connection.db.listCollections().toArray();

140

for (const collection of collections) {

141

await this.connection.collection(collection.name).createIndex({ createdAt: -1 });

142

}

143

}

144

}

145

146

// Named connection injection

147

@Injectable()

148

export class MultiDbService {

149

constructor(

150

@InjectConnection('users-db') private usersConnection: Connection,

151

@InjectConnection('orders-db') private ordersConnection: Connection,

152

) {}

153

154

async syncUserData(userId: string): Promise<void> {

155

const session = await this.usersConnection.startSession();

156

try {

157

await session.withTransaction(async () => {

158

// Perform operations within transaction

159

const user = await this.usersConnection.collection('users').findOne({ _id: userId });

160

if (user) {

161

await this.usersConnection.collection('user_cache').replaceOne(

162

{ userId },

163

{ ...user, lastSync: new Date() },

164

{ upsert: true }

165

);

166

}

167

});

168

} finally {

169

await session.endSession();

170

}

171

}

172

}

173

174

// Transaction management with connection and models

175

@Injectable()

176

export class TransactionService {

177

constructor(

178

@InjectConnection() private connection: Connection,

179

@InjectModel(User.name) private userModel: Model<User>,

180

@InjectModel(Order.name) private orderModel: Model<Order>,

181

) {}

182

183

async createUserAndOrder(userData: any, orderData: any): Promise<{ user: User; order: Order }> {

184

const session = await this.connection.startSession();

185

186

try {

187

const result = await session.withTransaction(async () => {

188

// Create user within transaction

189

const user = new this.userModel(userData);

190

await user.save({ session });

191

192

// Create order within same transaction

193

const order = new this.orderModel({ ...orderData, userId: user._id });

194

await order.save({ session });

195

196

return { user, order };

197

});

198

199

return result;

200

} finally {

201

await session.endSession();

202

}

203

}

204

}

205

```

206

207

## Utility Functions

208

209

### getModelToken

210

211

Generates the dependency injection token used for model injection.

212

213

```typescript { .api }

214

/**

215

* Generates dependency injection token for a model

216

* @param model - Model name

217

* @param connectionName - Optional connection name

218

* @returns DI token string

219

*/

220

function getModelToken(model: string, connectionName?: string): string;

221

```

222

223

**Usage Examples:**

224

225

```typescript

226

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

227

228

// Get token for default connection

229

const userToken = getModelToken('User');

230

// Returns: 'UserModel'

231

232

// Get token for named connection

233

const userTokenWithConnection = getModelToken('User', 'users-db');

234

// Returns: 'users-db/UserModel'

235

236

// Use in custom providers

237

const providers = [

238

{

239

provide: 'CUSTOM_USER_SERVICE',

240

useFactory: (userModel: Model<User>) => {

241

return new CustomUserService(userModel);

242

},

243

inject: [getModelToken(User.name)],

244

},

245

];

246

```

247

248

### getConnectionToken

249

250

Generates the dependency injection token used for connection injection.

251

252

```typescript { .api }

253

/**

254

* Generates dependency injection token for a connection

255

* @param name - Optional connection name

256

* @returns DI token string

257

*/

258

function getConnectionToken(name?: string): string;

259

```

260

261

**Usage Examples:**

262

263

```typescript

264

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

265

266

// Get token for default connection

267

const defaultConnectionToken = getConnectionToken();

268

// Returns: 'DatabaseConnection'

269

270

// Get token for named connection

271

const namedConnectionToken = getConnectionToken('users-db');

272

// Returns: 'users-db'

273

274

// Use in custom providers

275

const providers = [

276

{

277

provide: 'DATABASE_HEALTH_CHECK',

278

useFactory: (connection: Connection) => {

279

return new DatabaseHealthCheck(connection);

280

},

281

inject: [getConnectionToken()],

282

},

283

];

284

```

285

286

## Advanced Integration Patterns

287

288

### Custom Providers with Tokens

289

290

```typescript

291

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

292

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

293

294

const customProviders: Provider[] = [

295

{

296

provide: 'USER_REPOSITORY',

297

useFactory: (userModel: Model<User>) => {

298

return new UserRepository(userModel);

299

},

300

inject: [getModelToken(User.name)],

301

},

302

{

303

provide: 'DATABASE_MANAGER',

304

useFactory: (connection: Connection) => {

305

return new DatabaseManager(connection);

306

},

307

inject: [getConnectionToken()],

308

},

309

];

310

311

@Module({

312

providers: [...customProviders],

313

exports: ['USER_REPOSITORY', 'DATABASE_MANAGER'],

314

})

315

export class CustomModule {}

316

```

317

318

### Testing with Injection Tokens

319

320

```typescript

321

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

322

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

323

324

describe('UserService', () => {

325

let service: UserService;

326

let model: Model<User>;

327

328

beforeEach(async () => {

329

const module: TestingModule = await Test.createTestingModule({

330

providers: [

331

UserService,

332

{

333

provide: getModelToken(User.name),

334

useValue: {

335

find: jest.fn(),

336

findById: jest.fn(),

337

create: jest.fn(),

338

save: jest.fn(),

339

},

340

},

341

],

342

}).compile();

343

344

service = module.get<UserService>(UserService);

345

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

346

});

347

348

it('should find all users', async () => {

349

const users = [{ name: 'Test User' }];

350

jest.spyOn(model, 'find').mockReturnValue({

351

exec: jest.fn().mockResolvedValue(users),

352

} as any);

353

354

const result = await service.findAll();

355

expect(result).toEqual(users);

356

});

357

});

358

```