@project-karin/mongoose
v0.5.21
Published
MongoDB integration plugin for Karin using Mongoose ODM with enterprise-grade error handling.
Readme
@project-karin/mongoose
MongoDB integration plugin for Karin using Mongoose ODM with enterprise-grade error handling.
Installation
bun add @project-karin/mongoose mongooseOverview
The Mongoose plugin provides:
- ✅ MongoDB connection management
- ✅ Schema-based models with decorators
- ✅ Automatic error handling (ValidationError, CastError, etc.)
- ✅ Dependency injection for models
- ✅ Lazy configuration resolution
Quick Start
import { Schema, Prop, InjectModel } from "@project-karin/mongoose";
import { Model } from "mongoose";
// Define a schema
@Schema()
class User {
@Prop({ required: true })
name: string;
@Prop({ required: true, unique: true })
email: string;
@Prop()
age?: number;
}
// Use in a service
@Service()
class UsersService {
constructor(@InjectModel(User) private userModel: Model<User>) {}
async create(data: Partial<User>) {
return this.userModel.create(data);
}
async findAll() {
return this.userModel.find();
}
}
// Configure plugin
const app = await KarinFactory.create(adapter, {
plugins: [
new MongoosePlugin({
uri: "mongodb://localhost:27017/mydb",
models: [User], // Explicitly register models
}),
],
});Features
Schema Decorators
Define MongoDB schemas with TypeScript decorators:
import { Schema, Prop } from "@project-karin/mongoose";
@Schema({ timestamps: true })
class Product {
@Prop({ required: true, minlength: 3 })
name: string;
@Prop({ required: true, min: 0 })
price: number;
@Prop({ type: [String], default: [] })
tags: string[];
@Prop({ type: Object })
metadata?: Record<string, any>;
}Model Injection
Inject models into services:
import { InjectModel } from "@project-karin/mongoose";
import { Model } from "mongoose";
@Service()
class ProductsService {
constructor(@InjectModel(Product) private productModel: Model<Product>) {}
async findByTag(tag: string) {
return this.productModel.find({ tags: tag });
}
}Automatic Error Handling
The plugin automatically handles Mongoose errors:
// ValidationError → 400 Bad Request
{
"statusCode": 400,
"error": "Validation Error",
"message": "The provided data is invalid",
"details": [
{
"field": "email",
"message": "Path `email` is invalid (not-an-email)."
}
]
}
// CastError → 400 Bad Request
{
"statusCode": 400,
"error": "Invalid ID",
"message": "The value 'invalid-id' is not a valid ID"
}
// Duplicate Key → 409 Conflict
{
"statusCode": 409,
"error": "Duplicate Entry",
"message": "A record with this email already exists"
}Lazy Configuration
Use with ConfigPlugin for dynamic configuration:
const config = new ConfigPlugin({
requiredKeys: ["MONGO_URI", "DB_NAME"],
});
const app = await KarinFactory.create(adapter, {
plugins: [
config,
new MongoosePlugin({
uri: () => config.get("MONGO_URI"),
options: () => ({
dbName: config.get("DB_NAME"),
authSource: "admin",
}),
models: [User, Product], // Always register models explicitly
}),
],
});Model Registration
It is required to explicitly register your models in the plugin configuration. This ensures that Mongoose loads them correctly in all environments, including Serverless (Cloudflare Workers, Deno Deploy) and standard Bun runtimes.
new MongoosePlugin({
uri: "mongodb://...",
models: [User, Product, Order], // Required for both Server and Serverless
})Serverless Configuration
When running in serverless environments (AWS Lambda, Cloudflare Workers, etc.), it is crucial to optimize connection pooling to avoid exhausting database connections.
new MongoosePlugin({
uri: process.env.MONGO_URI,
options: () => ({
maxPoolSize: 2, // Keep this low (1-10) for serverless
minPoolSize: 0,
serverSelectionTimeoutMS: 5000, // Fail fast
}),
models: [User],
})API
MongoosePlugin Options
interface MongoosePluginOptions {
// MongoDB connection URI
uri: string | (() => string);
// Mongoose connection options
options?: ConnectOptions | (() => ConnectOptions);
// Models to register (for serverless)
models?: Function[];
// Auto-register exception filter (default: true)
autoRegisterExceptionFilter?: boolean;
// Enable serverless mode (reuses connections, skips disconnect)
// Default: Automatically detected via environment variables (AWS_LAMBDA_FUNCTION_NAME, VERCEL, etc.)
serverless?: boolean;
}Decorators
@Schema(options?)- Define a Mongoose schema@Prop(options?)- Define a schema property@InjectModel(model)- Inject a Mongoose model
Error Filter
Disable automatic error handling if needed:
new MongoosePlugin({
uri: "...",
autoRegisterExceptionFilter: false, // Provide your own filter
})Best Practices
- Use schemas for data validation
- Inject models instead of importing them
- Enable timestamps for audit trails
- Use indexes for performance
- Handle errors at the service layer when needed
License
MIT
