const fs = require('fs'); const net = require('net'); const path = require('path'); require('dotenv').config(); const DEFAULT_MONGO_URI = 'mongodb://127.0.0.1:27017/LibreChat-e2e'; const DEFAULT_RUNTIME_ENV_PATH = path.resolve(__dirname, '../specs/.test-results/runtime-env.json'); let mongoServer; function decodeMongoValue(value) { try { return decodeURIComponent(value); } catch { return value; } } function getMongoScheme(uri) { const schemeEnd = uri.indexOf('://'); return schemeEnd === -1 ? '' : uri.slice(0, schemeEnd).toLowerCase(); } function getMongoAuthority(uri) { const schemeEnd = uri.indexOf('://'); if (schemeEnd === -1) { return ''; } const withoutScheme = uri.slice(schemeEnd + 3); return withoutScheme.split(/[/?#]/, 1)[0]; } function getMongoDbName(uri) { const schemeEnd = uri.indexOf('://'); if (schemeEnd === -1) { return 'LibreChat-e2e'; } const withoutScheme = uri.slice(schemeEnd + 3); const pathStart = withoutScheme.indexOf('/'); if (pathStart === -1) { return 'LibreChat-e2e'; } const pathname = withoutScheme.slice(pathStart + 1).split(/[?#]/, 1)[0]; const dbName = pathname.split('/', 1)[0]; return dbName ? decodeMongoValue(dbName) : 'LibreChat-e2e'; } function normalizeMongoPort(port) { const parsed = Number(port); return Number.isInteger(parsed) && parsed > 0 && parsed <= 65535 ? parsed : 27017; } function parseMongoHost(hostEntry) { if (!hostEntry) { return null; } if (hostEntry.startsWith('[')) { const hostEnd = hostEntry.indexOf(']'); if (hostEnd === -1) { return null; } const host = hostEntry.slice(1, hostEnd); const port = hostEntry[hostEnd + 1] === ':' ? hostEntry.slice(hostEnd + 2) : ''; return { host, port: normalizeMongoPort(port) }; } const [host, port] = hostEntry.split(':'); return host ? { host, port: normalizeMongoPort(port) } : null; } function parseMongoUri(uri) { const scheme = getMongoScheme(uri); const authority = getMongoAuthority(uri); const hosts = authority .slice(authority.lastIndexOf('@') + 1) .split(',') .filter(Boolean); const parsedHost = scheme === 'mongodb+srv' || hosts.length !== 1 ? null : parseMongoHost(hosts[0]); return { dbName: getMongoDbName(uri), host: parsedHost?.host ?? '', port: parsedHost?.port ?? 27017, canProbe: Boolean(parsedHost), }; } function isLocalHost(host) { return host === 'localhost' || host === '127.0.0.1' || host === '::1'; } async function canConnect(host, port) { return new Promise((resolve) => { const socket = net.createConnection({ host, port }); const done = (result) => { socket.destroy(); resolve(result); }; socket.setTimeout(500); socket.once('connect', () => done(true)); socket.once('timeout', () => done(false)); socket.once('error', () => done(false)); }); } function withDbName(uri, dbName) { const parsed = new URL(uri); parsed.pathname = `/${dbName}`; return parsed.toString(); } function writeRuntimeEnv() { const runtimeEnvPath = process.env.E2E_RUNTIME_ENV_PATH || DEFAULT_RUNTIME_ENV_PATH; fs.mkdirSync(path.dirname(runtimeEnvPath), { recursive: true }); fs.writeFileSync(runtimeEnvPath, JSON.stringify({ MONGO_URI: process.env.MONGO_URI }, null, 2)); } async function maybeStartMemoryMongo() { const mongoUri = process.env.MONGO_URI ?? DEFAULT_MONGO_URI; const mode = process.env.E2E_USE_MEMORY_MONGO ?? 'auto'; if (mode === 'false') { process.env.MONGO_URI = mongoUri; writeRuntimeEnv(); return; } const { dbName, host, port, canProbe } = parseMongoUri(mongoUri); if (mode === 'auto' && (!canProbe || !isLocalHost(host) || (await canConnect(host, port)))) { process.env.MONGO_URI = mongoUri; writeRuntimeEnv(); return; } const { MongoMemoryServer } = require('mongodb-memory-server'); mongoServer = await MongoMemoryServer.create({ instance: { dbName, ip: '127.0.0.1', }, }); process.env.MONGO_URI = withDbName(mongoServer.getUri(), dbName); writeRuntimeEnv(); console.log(`[e2e] Started memory MongoDB at ${process.env.MONGO_URI}`); } async function shutdown() { if (mongoServer) { await mongoServer.stop(); } } process.once('SIGINT', async () => { await shutdown(); process.exit(130); }); process.once('SIGTERM', async () => { await shutdown(); process.exit(143); }); function startServer() { return maybeStartMemoryMongo() .then(() => { require(path.resolve(__dirname, '../../api/server/index.js')); }) .catch((error) => { console.error('[e2e] Failed to start test server:', error); process.exit(1); }); } if (require.main === module) { startServer(); } module.exports = { parseMongoUri, startServer, };