mongodb-rag-core
Version:
Common elements used by MongoDB Chatbot Framework components.
80 lines • 2.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeMongoshQuery = void 0;
const mongodb_1 = require("mongodb");
const child_process_1 = require("child_process");
const util_1 = require("util");
const redactMongoDbConnectionUri_1 = require("./redactMongoDbConnectionUri");
const execAsync = (0, util_1.promisify)(child_process_1.exec);
/**
Executes MongoDB query using `mongosh` CLI.
Note that Mongosh must be installed on the system running this function
for it to successfully execute.
*/
const executeMongoshQuery = async ({ query, uri, databaseName, execOptions, }) => {
let result = null;
let error = undefined;
let executionTimeMs = null;
try {
const connectionUrl = new URL(uri);
connectionUrl.pathname = databaseName;
const startTime = Date.now();
const modifiedQuery = appendToArrayIfNeeded(query);
const escapedQuery = modifiedQuery.replace(/'/g, "'\\''");
const { stdout, stderr } = await execAsync(`mongosh "${connectionUrl.toString()}" --quiet --json=relaxed --eval '${escapedQuery}'`, {
maxBuffer: 1024 * 1024 * 30, // 30 MB
timeout: 30000,
...execOptions,
});
const endTime = Date.now();
executionTimeMs = endTime - startTime;
if (stderr && stderr.trim()) {
error = { message: stderr.trim() };
executionTimeMs = null;
}
else if (stdout.trim()) {
try {
result = mongodb_1.BSON.EJSON.parse(stdout.trim(), { relaxed: true });
}
catch (parseError) {
error = {
message: `Failed to parse mongosh output: ${parseError.message}`,
};
executionTimeMs = null;
}
}
}
catch (execError) {
error = {
message: execError.message || "Failed to execute mongosh command",
};
}
// Redact any MongoDB connection URIs in error messages
if (error && error.message) {
error.message = (0, redactMongoDbConnectionUri_1.redactMongoDbConnectionUri)(error.message);
}
const data = {
result,
executionTimeMs,
error,
};
return data;
};
exports.executeMongoshQuery = executeMongoshQuery;
/**
Append .toArray() to cursor-returning operations if not already present.
*/
function appendToArrayIfNeeded(query) {
query = query.trim();
// Don't add .toArray() if .explain() is present or .toArray() already exists
if (query.includes(".explain(") || query.includes(".toArray()")) {
return query;
}
// Regex to match cursor-returning operations
const cursorReturningOperations = /(db\.\w+\.(find|aggregate|listCollections|listIndexes)\()/;
if (cursorReturningOperations.test(query)) {
return query.replace(/\)\s*;?$/, ").toArray();");
}
return query;
}
//# sourceMappingURL=executeMongoshQuery.js.map