import * as plugins from '../../plugins.js'; import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js'; import type { IStoredDocument } from '../../types/interfaces.js'; /** * InsertHandler - Handles insert commands */ export class InsertHandler implements ICommandHandler { async handle(context: IHandlerContext): Promise { const { storage, database, command, documentSequences } = context; const collection = command.insert; if (typeof collection !== 'string') { return { ok: 0, errmsg: 'insert command requires a collection name', code: 2, codeName: 'BadValue', }; } // Get documents from command or document sequences let documents: plugins.bson.Document[] = command.documents || []; // Check for OP_MSG document sequences (for bulk inserts) if (documentSequences && documentSequences.has('documents')) { documents = documentSequences.get('documents')!; } if (!Array.isArray(documents) || documents.length === 0) { return { ok: 0, errmsg: 'insert command requires documents array', code: 2, codeName: 'BadValue', }; } const ordered = command.ordered !== false; const writeErrors: plugins.bson.Document[] = []; let insertedCount = 0; // Ensure collection exists await storage.createCollection(database, collection); const indexEngine = context.getIndexEngine(collection); // Insert documents for (let i = 0; i < documents.length; i++) { const doc = documents[i]; try { // Ensure _id exists if (!doc._id) { doc._id = new plugins.bson.ObjectId(); } // Check index constraints before insert (doc now has _id) await indexEngine.onInsert(doc as IStoredDocument); await storage.insertOne(database, collection, doc); insertedCount++; } catch (error: any) { const writeError: plugins.bson.Document = { index: i, code: error.code || 11000, errmsg: error.message || 'Insert failed', }; // Check for duplicate key error if (error.message?.includes('Duplicate key')) { writeError.code = 11000; writeError.keyPattern = { _id: 1 }; writeError.keyValue = { _id: doc._id }; } writeErrors.push(writeError); if (ordered) { // Stop on first error for ordered inserts break; } } } const response: plugins.bson.Document = { ok: 1, n: insertedCount, }; if (writeErrors.length > 0) { response.writeErrors = writeErrors; } return response; } }