CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-mongoose

Mongoose is a comprehensive MongoDB object modeling tool designed for asynchronous environments with schema-based validation, query building, and business logic hooks.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

utilities.mddocs/

Utilities and Configuration

Global configuration, helper functions, type utilities, and debugging tools for Mongoose applications with comprehensive customization options.

Capabilities

Global Configuration

Configure Mongoose behavior globally with various options for connections, schemas, and operations.

/**
 * Set global Mongoose option
 * @param option - Option name
 * @param value - Option value
 * @returns Mongoose instance
 */
mongoose.set(option: string, value: any): typeof mongoose;

/**
 * Get global Mongoose option value
 * @param option - Option name
 * @returns Current option value
 */
mongoose.get(option: string): any;

// Available global options
type MongooseOptions = {
  /** Auto-create indexes from schema */
  autoIndex: boolean;
  
  /** Auto-create collections */
  autoCreate: boolean;
  
  /** Auto-create search indexes */
  autoSearchIndex: boolean;
  
  /** Buffer commands when disconnected */
  bufferCommands: boolean;
  
  /** Max number of buffered commands */
  bufferMaxEntries: number;
  
  /** Use createIndex instead of deprecated ensureIndex */
  useCreateIndex: boolean;
  
  /** Use findOneAndUpdate instead of deprecated findAndModify */
  useFindAndModify: boolean;
  
  /** Use new URL parser */
  useNewUrlParser: boolean;
  
  /** Use unified topology */
  useUnifiedTopology: boolean;
  
  /** Default strict mode for schemas */
  strict: boolean | 'throw';
  
  /** Strict mode for queries */
  strictQuery: boolean | 'throw';
  
  /** Strict mode for populate */
  strictPopulate: boolean;
  
  /** Run validators on update operations */
  runValidators: boolean;
  
  /** Return original document in findAndModify operations */
  returnOriginal: boolean;
  
  /** Minimize empty objects in documents */
  minimize: boolean;
  
  /** Automatically translate field aliases */
  translateAliases: boolean;
  
  /** Automatically sanitize query filters */
  sanitizeFilter: boolean;
  
  /** Transform POJOs to Mixed type */
  typePojoToMixed: boolean;
  
  /** Auto-select populated paths */
  selectPopulatedPaths: boolean;
  
  /** Maximum time for operations */
  maxTimeMS: number;
  
  /** Default transform function */
  transform: Function;
  
  /** JSON transform function */
  toJSON: Function;
  
  /** Object transform function */
  toObject: Function;
};

Usage Examples:

// Common global configurations
mongoose.set('strictQuery', false); // Allow flexible queries
mongoose.set('autoIndex', false); // Disable auto-indexing in production
mongoose.set('bufferCommands', false); // Fail fast when disconnected
mongoose.set('sanitizeFilter', true); // Auto-sanitize query filters
mongoose.set('returnOriginal', false); // Return updated documents

// Development vs Production settings
if (process.env.NODE_ENV === 'development') {
  mongoose.set('debug', true); // Enable query logging
  mongoose.set('autoIndex', true); // Auto-create indexes
} else {
  mongoose.set('autoIndex', false); // Manual index management
  mongoose.set('bufferMaxEntries', 0); // Fail immediately if disconnected
}

// Validation settings
mongoose.set('runValidators', true); // Validate on updates
mongoose.set('strictQuery', 'throw'); // Throw on invalid query fields

// Get current settings
console.log('Auto-indexing:', mongoose.get('autoIndex'));
console.log('Strict mode:', mongoose.get('strict'));

Plugin System

Register global and schema-specific plugins for extending Mongoose functionality.

/**
 * Register global plugin
 * @param fn - Plugin function
 * @param opts - Plugin options
 * @returns Mongoose instance
 */
mongoose.plugin(fn: Function, opts?: any): typeof mongoose;

/**
 * Plugin function signature
 * @param schema - Schema to apply plugin to
 * @param options - Plugin options
 */
type PluginFunction = (schema: Schema, options?: any) => void;

Usage Examples:

// Built-in plugins
const mongooseLeanDefaults = require('mongoose-lean-defaults');
const mongooseSlugPlugin = require('mongoose-slug-plugin');

// Register global plugins
mongoose.plugin(mongooseLeanDefaults);
mongoose.plugin(mongooseSlugPlugin, { field: 'title' });

// Custom timestamp plugin
function timestampPlugin(schema, options) {
  const { createdPath = 'createdAt', updatedPath = 'updatedAt' } = options || {};
  
  schema.add({
    [createdPath]: { type: Date, default: Date.now },
    [updatedPath]: { type: Date, default: Date.now }
  });
  
  schema.pre('save', function() {
    if (this.isModified() && !this.isNew) {
      this[updatedPath] = new Date();
    }
  });
  
  schema.pre(['updateOne', 'updateMany', 'findOneAndUpdate'], function() {
    this.set({ [updatedPath]: new Date() });
  });
}

// Apply to all schemas
mongoose.plugin(timestampPlugin);

// Apply to specific schema with options
userSchema.plugin(timestampPlugin, {
  createdPath: 'created',
  updatedPath: 'modified'
});

// Validation plugin
function validationPlugin(schema) {
  schema.post('save', function(error, doc, next) {
    if (error.name === 'MongoError' && error.code === 11000) {
      next(new Error('Duplicate key error'));
    } else {
      next(error);
    }
  });
}

mongoose.plugin(validationPlugin);

Type Utilities

Utility functions for working with MongoDB types and ObjectIds.

/**
 * Check if value is a valid ObjectId
 * @param value - Value to check
 * @returns true if valid ObjectId
 */
mongoose.isValidObjectId(value: any): boolean;

/**
 * Check if value is ObjectId or 24-character hex string
 * @param value - Value to check
 * @returns true if ObjectId or hex string
 */
mongoose.isObjectIdOrHexString(value: any): boolean;

/**
 * Cast value to ObjectId
 * @param value - Value to cast
 * @returns ObjectId instance
 */
mongoose.Types.ObjectId(value?: string | number | ObjectId): ObjectId;

/**
 * Sanitize query filters against injection attacks
 * @param filter - Query filter object
 * @returns Sanitized filter object
 */
mongoose.sanitizeFilter<T>(filter: FilterQuery<T>): FilterQuery<T>;

/**
 * Mark object as trusted (skip query sanitization)
 * @param obj - Object to mark as trusted
 * @returns Trusted object
 */
mongoose.trusted(obj: any): any;

/**
 * Cast value to specified type
 * @param type - Schema type to cast to
 * @param value - Value to cast
 * @param path - Path name for error reporting
 * @param doc - Document context
 * @returns Cast value
 */
mongoose.cast(type: any, value: any, path?: string, doc?: Document): any;

/**
 * Get current timestamp function
 * @returns Function that returns current Date
 */
mongoose.now(): () => Date;

/**
 * Skip middleware execution for a result
 * @param result - Result to skip middleware for
 * @returns Modified result
 */
mongoose.skipMiddlewareFunction(result: any): any;

/**
 * Overwrite middleware result
 * @param result - Result to overwrite
 * @returns Modified result
 */
mongoose.overwriteMiddlewareResult(result: any): any;

/**
 * Set custom MongoDB driver
 * @param driver - MongoDB driver object
 * @returns Mongoose instance
 */
mongoose.setDriver(driver: any): typeof mongoose;

/**
 * Remove undefined properties from object
 * @param val - Object to clean
 * @returns Object without undefined properties
 */
mongoose.omitUndefined<T>(val: T): T;

/**
 * Generate new ObjectId
 * @returns New ObjectId
 */
mongoose.Types.ObjectId(): ObjectId;

/**
 * Get ObjectId from timestamp
 * @param timestamp - Unix timestamp
 * @returns ObjectId representing the timestamp
 */
mongoose.Types.ObjectId.createFromTime(timestamp: number): ObjectId;

/**
 * Check if two ObjectIds are equal
 * @param a - First ObjectId
 * @param b - Second ObjectId  
 * @returns true if equal
 */
ObjectId.prototype.equals(b: ObjectId): boolean;

/**
 * Get timestamp from ObjectId
 * @returns Date object from ObjectId timestamp
 */
ObjectId.prototype.getTimestamp(): Date;

Usage Examples:

// Validate ObjectIds
const userId = req.params.id;
if (!mongoose.isValidObjectId(userId)) {
  return res.status(400).json({ error: 'Invalid user ID' });
}

// Check if string can be ObjectId
const possibleId = 'somestring';
if (mongoose.isObjectIdOrHexString(possibleId)) {
  const user = await User.findById(possibleId);
}

// Generate ObjectIds
const newId = new mongoose.Types.ObjectId();
console.log('New ID:', newId.toString());

// ObjectId from string
const id = new mongoose.Types.ObjectId('507f1f77bcf86cd799439011');

// ObjectId from timestamp
const timestampId = mongoose.Types.ObjectId.createFromTime(Math.floor(Date.now() / 1000));
console.log('ID from timestamp:', timestampId);

// Extract timestamp from ObjectId
const createdAt = userId.getTimestamp();
console.log('Document created at:', createdAt);

// Compare ObjectIds
if (user1._id.equals(user2._id)) {
  console.log('Same user');
}

// ObjectId utilities in queries
const recentIds = await User.find({
  _id: {
    $gte: mongoose.Types.ObjectId.createFromTime(Date.now() / 1000 - 3600) // Last hour
  }
}).select('_id name');

Collection Name Management

Configure how Mongoose generates collection names from model names.

/**
 * Get or set pluralization function
 * @param fn - Pluralization function (optional)
 * @returns Current pluralization function
 */
mongoose.pluralize(fn?: Function): Function;

// Default pluralization function signature
type PluralizationFunction = (name: string) => string;

Usage Examples:

// Default pluralization
console.log(mongoose.pluralize()('User')); // 'users'
console.log(mongoose.pluralize()('Person')); // 'people'
console.log(mongoose.pluralize()('Child')); // 'children'

// Custom pluralization
mongoose.pluralize((name) => {
  // Simple pluralization - just add 's'
  return name.toLowerCase() + 's';
});

// Disable pluralization
mongoose.pluralize(null);

// Complex custom pluralization
const inflection = require('inflection');
mongoose.pluralize((name) => {
  return inflection.pluralize(name).toLowerCase();
});

// Per-model collection names (overrides pluralization)
const User = mongoose.model('User', userSchema, 'custom_users');

Query Filter Sanitization

Protect against NoSQL injection attacks by sanitizing query filters.

/**
 * Sanitize query filter against injection attacks
 * @param filter - Query filter object
 * @returns Sanitized filter
 */
mongoose.sanitizeFilter<T>(filter: FilterQuery<T>): FilterQuery<T>;

/**
 * Mark object as trusted (bypass sanitization)
 * @param obj - Object to mark as trusted
 * @returns Trusted object
 */
mongoose.trusted(obj: any): any;

Usage Examples:

// Enable automatic sanitization
mongoose.set('sanitizeFilter', true);

// Manual sanitization
const userInput = req.body.filter; // Could contain { $where: 'malicious code' }
const safeFilter = mongoose.sanitizeFilter(userInput);
const users = await User.find(safeFilter);

// Trusted objects bypass sanitization
const adminQuery = mongoose.trusted({
  $where: 'this.role === "admin"' // Intentional $where usage
});
const admins = await User.find(adminQuery);

// Sanitization in practice
app.post('/users/search', async (req, res) => {
  try {
    // req.body might contain: { name: { $ne: null }, $where: "..." }
    const filter = mongoose.sanitizeFilter(req.body);
    // Sanitized to: { name: { $eq: { $ne: null } }, "$where": { $eq: "..." } }
    
    const users = await User.find(filter);
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Custom sanitization
function customSanitize(obj) {
  const sanitized = mongoose.sanitizeFilter(obj);
  
  // Additional custom logic
  if (sanitized.$text && !user.hasTextSearchPermission) {
    delete sanitized.$text;
  }
  
  return sanitized;
}

Connection State Management

Monitor and manage connection states with constants and utilities.

/**
 * Connection state constants
 */
mongoose.STATES: {
  disconnected: 0;
  connected: 1;
  connecting: 2;
  disconnecting: 3;
  uninitialized: 99;
};

/**
 * Check connection readiness
 * @returns true if connected
 */
mongoose.connection.readyState === mongoose.STATES.connected;

Usage Examples:

// Check connection state
function isConnected() {
  return mongoose.connection.readyState === mongoose.STATES.connected;
}

function getConnectionState() {
  const state = mongoose.connection.readyState;
  const states = {
    [mongoose.STATES.disconnected]: 'disconnected',
    [mongoose.STATES.connected]: 'connected',
    [mongoose.STATES.connecting]: 'connecting',
    [mongoose.STATES.disconnecting]: 'disconnecting',
    [mongoose.STATES.uninitialized]: 'uninitialized'
  };
  return states[state] || 'unknown';
}

// Wait for connection
async function waitForConnection(timeout = 10000) {
  return new Promise((resolve, reject) => {
    if (mongoose.connection.readyState === mongoose.STATES.connected) {
      return resolve(true);
    }
    
    const timer = setTimeout(() => {
      reject(new Error('Connection timeout'));
    }, timeout);
    
    mongoose.connection.once('connected', () => {
      clearTimeout(timer);
      resolve(true);
    });
    
    mongoose.connection.once('error', (error) => {
      clearTimeout(timer);
      reject(error);
    });
  });
}

// Health check endpoint
app.get('/health', (req, res) => {
  const dbState = getConnectionState();
  res.json({
    status: dbState === 'connected' ? 'healthy' : 'unhealthy',
    database: dbState,
    timestamp: new Date().toISOString()
  });
});

Index Management

Utilities for managing database indexes across all models.

/**
 * Synchronize indexes for all models
 * @param options - Sync options
 * @returns Promise resolving to sync results
 */
mongoose.syncIndexes(options?: SyncIndexesOptions): Promise<{ [modelName: string]: string[] }>;

interface SyncIndexesOptions {
  /** Continue on error */
  continueOnError?: boolean;
  
  /** Skip specific models */
  skip?: string[];
  
  /** Only sync specific models */
  only?: string[];
}

Usage Examples:

// Sync all indexes
const results = await mongoose.syncIndexes();
console.log('Index sync results:', results);

// Sync with options
const results = await mongoose.syncIndexes({
  continueOnError: true,
  skip: ['TempModel'] // Skip temporary models
});

// Production deployment script
async function deployIndexes() {
  try {
    console.log('Syncing database indexes...');
    const results = await mongoose.syncIndexes();
    
    Object.keys(results).forEach(modelName => {
      const operations = results[modelName];
      if (operations.length > 0) {
        console.log(`${modelName}: ${operations.join(', ')}`);
      }
    });
    
    console.log('Index synchronization completed');
  } catch (error) {
    console.error('Index sync failed:', error);
    throw error;
  }
}

// Manual index management
async function manageIndexes() {
  // Create indexes for specific model
  await User.createIndexes();
  
  // List existing indexes
  const indexes = await User.listIndexes();
  console.log('User indexes:', indexes);
  
  // Sync indexes for specific model
  const userSync = await User.syncIndexes();
  console.log('User index operations:', userSync);
}

Additional Utilities

Additional helper functions and middleware utilities for advanced Mongoose usage.

/**
 * Get current timestamp (Date.now)
 * @returns Current timestamp function
 */
mongoose.now(): () => Date;

/**
 * Cast value to schema type
 * @param type - Schema type or type name
 * @param value - Value to cast
 * @param path - Field path (optional)
 * @param doc - Document context (optional)
 * @returns Casted value
 */
mongoose.cast(type: any, value: any, path?: string, doc?: Document): any;

/**
 * Set MongoDB driver instance
 * @param driver - MongoDB driver to use
 * @returns Mongoose instance
 */
mongoose.setDriver(driver: any): typeof mongoose;

/**
 * Skip middleware execution and return result
 * @param result - Result to return, skipping middleware
 * @returns Special result object that skips middleware
 */
mongoose.skipMiddlewareFunction(result: any): any;

/**
 * Overwrite middleware result
 * @param result - New result to use instead of middleware result
 * @returns Special result object that overwrites middleware result
 */
mongoose.overwriteMiddlewareResult(result: any): any;

Usage Examples:

// Get current timestamp function
const timestampFn = mongoose.now();
console.log('Current time:', timestampFn()); // Current Date

// Cast values using schema types
const schema = new mongoose.Schema({ age: Number });
const castedAge = mongoose.cast(Number, '25'); // 25 (number)
const castedId = mongoose.cast(mongoose.Schema.Types.ObjectId, '507f1f77bcf86cd799439011');

// Set custom driver (advanced usage)
const customDriver = require('./custom-mongodb-driver');
mongoose.setDriver(customDriver);

// Middleware control (advanced)
userSchema.pre('save', function() {
  if (this.skipValidation) {
    return mongoose.skipMiddlewareFunction(this);
  }
  
  // Normal middleware logic
  this.updatedAt = new Date();
});

userSchema.post('save', function(result) {
  if (this.customResult) {
    return mongoose.overwriteMiddlewareResult(this.customResult);
  }
  return result;
});

Native Driver Access

Access underlying MongoDB driver and query builder for advanced operations.

/**
 * Native MongoDB driver reference
 */
mongoose.mongo: typeof mongodb;

/**
 * MQuery query builder reference
 */
mongoose.mquery: typeof mquery;

Usage Examples:

// Access native MongoDB driver
const { MongoClient, ObjectId } = mongoose.mongo;

// Use native operations
const db = mongoose.connection.db;
const result = await db.collection('users').aggregate([
  { $match: { status: 'active' } },
  { $group: { _id: '$department', count: { $sum: 1 } } }
]).toArray();

// Create native ObjectId
const nativeId = new mongoose.mongo.ObjectId();

// Access mquery for query building
const mquery = mongoose.mquery;
const query = mquery().find({ status: 'active' }).limit(10);

// Check driver versions
console.log('MongoDB driver version:', mongoose.mongo.version);
console.log('MQuery version:', mongoose.mquery.version);

Debugging and Development

Development tools for debugging queries, performance monitoring, and troubleshooting.

/**
 * Enable query debugging
 * @param enabled - Enable debug mode
 * @param options - Debug options
 * @returns Mongoose instance
 */
mongoose.set('debug', enabled: boolean | Function | DebugOptions): typeof mongoose;

interface DebugOptions {
  /** Include shell commands */
  shell?: boolean;
  
  /** Custom debug function */
  fn?: (collectionName: string, method: string, query: any, doc?: any) => void;
}

/**
 * Get Mongoose version
 */
mongoose.version: string;

/**
 * Access native MongoDB driver
 */
mongoose.mongo: typeof mongodb;

/**
 * Access mquery (query builder)
 */
mongoose.mquery: typeof mquery;

Usage Examples:

// Enable query debugging
mongoose.set('debug', true);

// Custom debug function
mongoose.set('debug', (collectionName, method, query, doc) => {
  console.log(`[${new Date().toISOString()}] ${collectionName}.${method}`, 
    JSON.stringify(query, null, 2));
});

// Conditional debugging
if (process.env.NODE_ENV === 'development') {
  mongoose.set('debug', true);
}

// Debug with shell commands
mongoose.set('debug', { shell: true });

// Performance monitoring
const originalExec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = function() {
  const startTime = Date.now();
  const result = originalExec.call(this);
  
  if (result && typeof result.then === 'function') {
    return result.then(res => {
      const duration = Date.now() - startTime;
      if (duration > 100) { // Log slow queries
        console.warn(`Slow query (${duration}ms):`, this.getQuery());
      }
      return res;
    });
  }
  
  return result;
};

// Version information
console.log('Mongoose version:', mongoose.version);
console.log('MongoDB driver version:', mongoose.mongo.version);

// Native driver access
const db = mongoose.connection.db;
const nativeCollection = db.collection('users');
const count = await nativeCollection.countDocuments({});

Types

interface MongooseGlobals {
  /** Mongoose version string */
  version: string;
  
  /** Connection state constants */
  STATES: {
    disconnected: 0;
    connected: 1;
    connecting: 2;
    disconnecting: 3;
    uninitialized: 99;
  };
  
  /** Type constructors */
  Types: {
    ObjectId: typeof ObjectId;
    Decimal128: typeof Decimal128;
    Array: typeof MongooseArray;
    DocumentArray: typeof MongooseDocumentArray;
    Buffer: typeof MongooseBuffer;
    Map: typeof MongooseMap;
    UUID: typeof UUID;
  };
  
  /** Schema type constructors */
  SchemaTypes: {
    String: typeof String;
    Number: typeof Number;
    Date: typeof Date;
    Boolean: typeof Boolean;
    ObjectId: typeof ObjectId;
    Buffer: typeof Buffer;
    Mixed: typeof Mixed;
    Array: typeof Array;
    Decimal128: typeof Decimal128;
    Map: typeof Map;
    UUID: typeof UUID;
    BigInt: typeof BigInt;
  };
  
  /** Error classes */
  Error: {
    MongooseError: typeof MongooseError;
    ValidationError: typeof ValidationError;
    ValidatorError: typeof ValidatorError;
    CastError: typeof CastError;
    DocumentNotFoundError: typeof DocumentNotFoundError;
    VersionError: typeof VersionError;
    ParallelSaveError: typeof ParallelSaveError;
    MissingSchemaError: typeof MissingSchemaError;
    OverwriteModelError: typeof OverwriteModelError;
  };
  
  /** Native MongoDB driver reference */
  mongo: typeof mongodb;
  
  /** Query builder reference */
  mquery: typeof mquery;
}

// Utility type helpers
type ObjectIdLike = string | ObjectId;
type FilterQuery<T> = { [P in keyof T]?: T[P] | QuerySelector<T[P]> } & QuerySelector<T>;
type UpdateQuery<T> = Partial<T> & MongoUpdateOperators;
type ProjectionType<T> = string | { [K in keyof T]?: 1 | 0 | boolean };

docs

aggregation.md

connection.md

document.md

errors.md

index.md

model.md

query.md

schema.md

utilities.md

tile.json