https://github.com/kisiwu/storehouse-mongodb
MongoDB driver manager for @storehouse/core.
https://github.com/kisiwu/storehouse-mongodb
database mongodb nodejs
Last synced: 2 months ago
JSON representation
MongoDB driver manager for @storehouse/core.
- Host: GitHub
- URL: https://github.com/kisiwu/storehouse-mongodb
- Owner: kisiwu
- License: mit
- Created: 2021-07-31T10:38:22.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2024-03-03T12:57:33.000Z (over 2 years ago)
- Last Synced: 2025-03-21T07:35:49.194Z (over 1 year ago)
- Topics: database, mongodb, nodejs
- Language: TypeScript
- Homepage:
- Size: 82 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @storehouse/mongodb
MongoDB driver manager adapter for [@storehouse/core](https://www.npmjs.com/package/@storehouse/core). Provides seamless integration with [MongoDB](https://www.mongodb.com/) using the official [Node.js driver](https://www.npmjs.com/package/mongodb).
## Features
- **Type-safe MongoDB operations** with TypeScript support
- **Connection lifecycle management** with automatic event logging
- **Health check utilities** for monitoring (works without admin privileges)
- **Multi-manager support** via Storehouse registry
- **Cross-database access** using dot notation
## Prerequisites
- **MongoDB server**
- **Node.js** 18 or higher
## Installation
```bash
npm install @storehouse/core mongodb @storehouse/mongodb
```
## Quick Start
### 1. Define Your Types
**models/movie.ts**
```ts
export interface Movie {
title: string;
director: string;
year: number;
rating?: number;
}
```
### 2. Register the Manager
**index.ts**
```ts
import { Storehouse } from '@storehouse/core';
import { MongoDbManager } from '@storehouse/mongodb';
// Register the manager
Storehouse.add({
mongodb: {
type: MongoDbManager,
config: {
url: 'mongodb://localhost:27017/mydb',
// MongoClientOptions
options: {
maxPoolSize: 10,
minPoolSize: 5
}
}
}
});
```
### 3. Connect and Use
```ts
import { Storehouse } from '@storehouse/core';
import { MongoDbManager } from '@storehouse/mongodb';
import { Collection, MongoClient } from 'mongodb';
import { Movie } from './models/movie';
// Get the manager and connect
const manager = Storehouse.getManager('mongodb');
if (manager) {
// Open the connection
await manager.connect();
console.log('Connected to database:', manager.db().databaseName);
// Get a collection
const moviesCollection = manager.getModel('movies');
// Insert a document
await moviesCollection.insertOne({
title: 'Sinners',
director: 'Ryan Coogler',
year: 2025,
rating: 8.5
});
// Query documents
const movies = await moviesCollection.find({ year: { $gte: 2010 } }).toArray();
console.log('Movies:', movies);
// Count documents
const count = await moviesCollection.countDocuments();
console.log('Total movies:', count);
}
```
## API Reference
### Helper Functions
The package provides helper functions that throw errors instead of returning undefined, making your code cleaner and safer.
#### `getManager()`
Retrieves a MongoDbManager instance from the registry.
```ts
import { Storehouse } from '@storehouse/core';
import { getManager } from '@storehouse/mongodb';
const manager = getManager(Storehouse, 'mongodb');
await manager.connect();
```
**Throws:**
- `ManagerNotFoundError` - If the manager doesn't exist
- `InvalidManagerConfigError` - If the manager is not a MongoDbManager instance
#### `getConnection()`
Retrieves the underlying MongoDB client connection.
```ts
import { Storehouse } from '@storehouse/core';
import { getConnection } from '@storehouse/mongodb';
const client = getConnection(Storehouse, 'mongodb');
await client.connect();
// Access the database
const db = client.db('mydb');
const collections = await db.listCollections().toArray();
```
**Throws:**
- `ManagerNotFoundError` - If the manager doesn't exist
- `InvalidManagerConfigError` - If the manager is not a MongoClient instance
#### `getModel()`
Retrieves a MongoDB Collection by name.
```ts
import { Storehouse } from '@storehouse/core';
import { getModel } from '@storehouse/mongodb';
import { Movie } from './models/movie';
// Get model from default manager
const movies = getModel(Storehouse, 'movies');
// Get model from specific manager
const users = getModel(Storehouse, 'mongodb', 'users');
// Use the collection
const count = await movies.countDocuments();
console.log('Total movies:', count);
```
**Throws:**
- `ModelNotFoundError` - If the model doesn't exist
### MongoDbManager Class
#### Methods
##### `connect(): Promise`
Establishes connection to MongoDB.
```ts
await manager.connect();
```
##### `close(force?: boolean): Promise`
Closes the MongoDB connection.
```ts
// Graceful close
await manager.close();
// Force close
await manager.close(true);
```
##### `closeConnection(force?: boolean): Promise`
Alias for `close()`. Closes the MongoDB connection.
```ts
await manager.closeConnection();
```
##### `getConnection(): MongoClient`
Returns the underlying MongoDB client instance.
```ts
const client = manager.getConnection();
const db = client.db('mydb');
```
##### `getModel(name: string): Collection`
Retrieves a MongoDB collection by name. Supports dot notation for cross-database access.
```ts
// Get collection from default database
const movies = manager.getModel('movies');
// Get collection from specific database
const users = manager.getModel('otherdb.users');
```
##### `isConnected(): Promise`
Checks if the connection is currently active. Works without admin privileges.
```ts
const connected = await manager.isConnected();
if (connected) {
console.log('MongoDB is connected');
}
```
##### `healthCheck(): Promise`
Performs a comprehensive health check including ping test and latency measurement. Works without admin privileges.
```ts
const health = await manager.healthCheck();
if (health.healthy) {
console.log(`✓ MongoDB is healthy`);
console.log(` Database: ${health.details.databaseName}`);
console.log(` Latency: ${health.details.latency}`);
} else {
console.error(`✗ MongoDB is unhealthy: ${health.message}`);
}
```
### Health Check Result
The health check returns a detailed result object:
- `healthy: boolean` - Overall health status
- `message: string` - Descriptive message about the health status
- `timestamp: number` - Timestamp when the health check was performed
- `latency?: number` - Response time in milliseconds
- `details: object` - Detailed connection information
- `name: string` - Manager name
- `isOpen: boolean` - Connection open status
- `isReady: boolean` - Connection ready status
- `pingResponse?: Document` - MongoDB ping response
- `latency?: string` - Response time in ms
- `error?: string` - Error details (if unhealthy)
## Advanced Usage
### Multiple Managers
You can register multiple MongoDB connections:
```ts
import { Storehouse } from '@storehouse/core';
import { MongoDbManager, getManager } from '@storehouse/mongodb';
Storehouse.add({
primary: {
type: MongoDbManager,
config: {
url: 'mongodb://localhost:27017/maindb'
}
},
analytics: {
type: MongoDbManager,
config: {
url: 'mongodb://localhost:27017/analyticsdb'
}
}
});
// Access specific managers
const primaryManager = getManager(Storehouse, 'primary');
const analyticsManager = getManager(Storehouse, 'analytics');
```
### Using the Manager Type
Set the manager type to simplify configuration and use string identifiers instead of class references:
```ts
import { Storehouse } from '@storehouse/core';
import { MongoDbManager } from '@storehouse/mongodb';
// Set default manager type
Storehouse.setManagerType(MongoDbManager);
// Now you can use type string instead of class
Storehouse.add({
mongodb: {
type: '@storehouse/mongodb',
config: {
url: 'mongodb://localhost:27017/mydb'
}
}
});
```
### Cross-Database Access
Access collections from different databases sharing the same socket connection using dot notation:
```ts
import { Storehouse } from '@storehouse/core';
import { getModel } from '@storehouse/mongodb';
// Access collection from another database
const otherDbMovies = getModel(Storehouse, 'mongodb', 'otherdatabase.movies');
// Or using Storehouse directly
const Movies = Storehouse.getModel('mongodb', 'otherdatabase.movies');
// Query the collection
const movies = await otherDbMovies?.find({}).toArray();
```
The format is: `.`
### Connection Event Handling
The manager automatically logs connection lifecycle events. These are logged using the `@novice1/logger` package and can be enabled with Debug mode:
```ts
import { Debug } from '@novice1/logger';
Debug.enable('@storehouse/mongodb*');
```
**Events logged:**
- `topologyOpening` - Connection initiated
- `serverOpening` - Server connection established
- `serverClosed` - Server connection closed
- `topologyClosed` - Connection closed
- `error` - Connection errors
## TypeScript Support
The package is written in TypeScript and provides full type definitions for type-safe operations:
```ts
import { Storehouse } from '@storehouse/core';
import { MongoClient, Collection } from 'mongodb';
import { MongoDbManager, getManager, getConnection, getModel } from '@storehouse/mongodb';
// Typed manager
const manager = getManager(Storehouse, 'mongodb');
// Typed connection
const client: MongoClient = getConnection(Storehouse, 'mongodb');
// Typed collection with document interface
interface User {
name: string;
email: string;
age: number;
}
const users = getModel(Storehouse, 'mongodb', 'users');
// users is typed as Collection
// Type-safe operations
const allUsers = await users.find({}).toArray();
// allUsers is typed as User[]
```
## Error Handling
All helper functions throw specific errors for better error handling:
```ts
import { Storehouse } from '@storehouse/core';
import { getManager, getModel, getConnection } from '@storehouse/mongodb';
import {
ManagerNotFoundError,
ModelNotFoundError,
InvalidManagerConfigError
} from '@storehouse/core';
try {
const manager = getManager(Storehouse, 'nonexistent');
} catch (error) {
if (error instanceof ManagerNotFoundError) {
console.error('Manager not found:', error.message);
} else if (error instanceof InvalidManagerConfigError) {
console.error('Invalid manager type:', error.message);
}
}
try {
const model = getModel(Storehouse, 'nonexistent');
} catch (error) {
if (error instanceof ModelNotFoundError) {
console.error('Model not found:', error.message);
}
}
```
## Best Practices
1. **Always connect** - Call `connect()` after registering the manager to establish the connection
2. **Use health checks** - Monitor connection health in production environments
3. **Handle disconnections** - Implement reconnection and retry logic for critical operations
4. **Close connections** - Always call `close()` when shutting down your application
5. **Use TypeScript** - Leverage type definitions for safer database operations
## Resources
- [Documentation](https://kisiwu.github.io/storehouse/mongodb/latest/)
- [@storehouse/core](https://www.npmjs.com/package/@storehouse/core)
- [MongoDB Node.js Driver](https://www.npmjs.com/package/mongodb)
- [MongoDB Documentation](https://www.mongodb.com/docs/)
## License
MIT