refactor: original changes

This commit is contained in:
Danny Avila 2025-05-30 04:28:22 -04:00
parent fa9177180f
commit f9c0e9853f
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
83 changed files with 413 additions and 505 deletions

View file

@ -21,25 +21,6 @@ jest.mock('~/lib/db/connectDb', () => {
}, },
}; };
}); });
jest.mock('@librechat/data-schemas', () => {
const userModelMock = {
createUser: jest.fn(() => mockUser),
findUser: jest.fn(),
updateUser: jest.fn(),
};
return {
registerModels: jest.fn().mockReturnValue({
User: userModelMock,
}),
};
});
jest.mock('~/models/Message', () => ({
Message: jest.fn(),
}));
jest.mock('~/models/Conversation', () => ({
Conversation: jest.fn(),
}));
jest.mock('~/models/File', () => ({ jest.mock('~/models/File', () => ({
File: jest.fn(), File: jest.fn(),
})); }));
@ -63,9 +44,6 @@ describe('Tool Handlers', () => {
const mainPlugin = availableTools.find((tool) => tool.pluginKey === pluginKey); const mainPlugin = availableTools.find((tool) => tool.pluginKey === pluginKey);
const authConfigs = mainPlugin.authConfig; const authConfigs = mainPlugin.authConfig;
const { registerModels } = require('@librechat/data-schemas');
let User = registerModels().User;
beforeAll(async () => { beforeAll(async () => {
mockUser.save.mockResolvedValue(undefined); mockUser.save.mockResolvedValue(undefined);

View file

@ -1,8 +1,8 @@
const { ViolationTypes } = require('librechat-data-provider'); const { ViolationTypes } = require('librechat-data-provider');
const { deleteAllUserSessions } = require('@librechat/data-schemas');
const { isEnabled, math, removePorts } = require('~/server/utils'); const { isEnabled, math, removePorts } = require('~/server/utils');
const getLogStores = require('./getLogStores'); const getLogStores = require('./getLogStores');
const { logger } = require('~/config'); const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { BAN_VIOLATIONS, BAN_INTERVAL } = process.env ?? {}; const { BAN_VIOLATIONS, BAN_INTERVAL } = process.env ?? {};
const interval = math(BAN_INTERVAL, 20); const interval = math(BAN_INTERVAL, 20);
@ -45,7 +45,7 @@ const banViolation = async (req, res, errorMessage) => {
return; return;
} }
await db.models.Session.deleteAllUserSessions({ userId: user_id }); await deleteAllUserSessions({ userId: user_id });
res.clearCookie('refreshToken'); res.clearCookie('refreshToken');
const banLogs = getLogStores(ViolationTypes.BAN); const banLogs = getLogStores(ViolationTypes.BAN);

View file

@ -1,17 +1,5 @@
const banViolation = require('./banViolation'); const banViolation = require('./banViolation');
jest.mock('@librechat/data-schemas', () => {
const sessionModelMock = {
deleteAllUserSessions: jest.fn(),
};
return {
registerModels: jest.fn().mockReturnValue({
Session: sessionModelMock,
}),
};
});
const mockModels = { const mockModels = {
Session: { Session: {
deleteAllUserSessions: jest.fn(), deleteAllUserSessions: jest.fn(),

View file

@ -1,6 +1,5 @@
require('dotenv').config(); require('dotenv').config();
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { registerModels } = require('@librechat/data-schemas');
if (!process.env.MONGO_URI) { if (!process.env.MONGO_URI) {
throw new Error('Please define the MONGO_URI environment variable'); throw new Error('Please define the MONGO_URI environment variable');
@ -40,11 +39,6 @@ async function connectDb(mongoUri = process.env.MONGO_URI) {
} }
cached.conn = await cached.promise; cached.conn = await cached.promise;
// Register models once
if (!cached.models) {
cached.models = registerModels(mongoose);
}
return cached.conn; return cached.conn;
} }

View file

@ -1,7 +1,6 @@
const { MeiliSearch } = require('meilisearch'); const { MeiliSearch } = require('meilisearch');
const { Message, Conversation, logger } = require('@librechat/data-schemas');
const { isEnabled } = require('~/server/utils'); const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const searchEnabled = isEnabled(process.env.SEARCH); const searchEnabled = isEnabled(process.env.SEARCH);
const indexingDisabled = isEnabled(process.env.MEILI_NO_SYNC); const indexingDisabled = isEnabled(process.env.MEILI_NO_SYNC);
@ -28,7 +27,6 @@ async function indexSync() {
if (!searchEnabled) { if (!searchEnabled) {
return; return;
} }
const { Message, Conversation } = db.models;
try { try {
const client = MeiliSearchClient.getInstance(); const client = MeiliSearchClient.getInstance();
@ -42,6 +40,8 @@ async function indexSync() {
return; return;
} }
logger.info('[indexSync] Starting index sync...');
const messageCount = await Message.countDocuments(); const messageCount = await Message.countDocuments();
const convoCount = await Conversation.countDocuments(); const convoCount = await Conversation.countDocuments();
const messages = await client.index('messages').getStats(); const messages = await client.index('messages').getStats();

View file

@ -1,5 +1,6 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const crypto = require('node:crypto'); const crypto = require('node:crypto');
const { Agent } = require('@librechat/data-schemas');
const { SystemRoles, Tools, actionDelimiter } = require('librechat-data-provider'); const { SystemRoles, Tools, actionDelimiter } = require('librechat-data-provider');
const { GLOBAL_PROJECT_NAME, EPHEMERAL_AGENT_ID, mcp_delimiter } = const { GLOBAL_PROJECT_NAME, EPHEMERAL_AGENT_ID, mcp_delimiter } =
require('librechat-data-provider').Constants; require('librechat-data-provider').Constants;
@ -14,8 +15,6 @@ const getLogStores = require('~/cache/getLogStores');
const { getActions } = require('./Action'); const { getActions } = require('./Action');
const { logger } = require('~/config'); const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/** /**
* Create an agent with the provided data. * Create an agent with the provided data.
* @param {Object} agentData - The agent data to create. * @param {Object} agentData - The agent data to create.
@ -35,7 +34,7 @@ const createAgent = async (agentData) => {
}, },
], ],
}; };
return (await db.models.Agent.create(initialAgentData)).toObject(); return (await Agent.create(initialAgentData)).toObject();
}; };
/** /**
@ -46,7 +45,7 @@ const createAgent = async (agentData) => {
* @param {string} searchParameter.author - The user ID of the agent's author. * @param {string} searchParameter.author - The user ID of the agent's author.
* @returns {Promise<Agent|null>} The agent document as a plain object, or null if not found. * @returns {Promise<Agent|null>} The agent document as a plain object, or null if not found.
*/ */
const getAgent = async (searchParameter) => await db.models.Agent.findOne(searchParameter).lean(); const getAgent = async (searchParameter) => await Agent.findOne(searchParameter).lean();
/** /**
* Load an agent based on the provided ID * Load an agent based on the provided ID
@ -268,7 +267,6 @@ const updateAgent = async (searchParameter, updateData, options = {}) => {
const { updatingUserId = null, forceVersion = false } = options; const { updatingUserId = null, forceVersion = false } = options;
const mongoOptions = { new: true, upsert: false }; const mongoOptions = { new: true, upsert: false };
const Agent = db.models?.Agent;
const currentAgent = await Agent.findOne(searchParameter); const currentAgent = await Agent.findOne(searchParameter);
if (currentAgent) { if (currentAgent) {
const { __v, _id, id, versions, author, ...versionData } = currentAgent.toObject(); const { __v, _id, id, versions, author, ...versionData } = currentAgent.toObject();
@ -362,7 +360,6 @@ const updateAgent = async (searchParameter, updateData, options = {}) => {
* @returns {Promise<Agent>} The updated agent. * @returns {Promise<Agent>} The updated agent.
*/ */
const addAgentResourceFile = async ({ req, agent_id, tool_resource, file_id }) => { const addAgentResourceFile = async ({ req, agent_id, tool_resource, file_id }) => {
const Agent = db.models?.Agent;
const searchParameter = { id: agent_id }; const searchParameter = { id: agent_id };
let agent = await getAgent(searchParameter); let agent = await getAgent(searchParameter);
if (!agent) { if (!agent) {
@ -428,7 +425,7 @@ const removeAgentResourceFiles = async ({ agent_id, files }) => {
} }
const updatePullData = { $pull: pullOps }; const updatePullData = { $pull: pullOps };
const agentAfterPull = await db.models.Agent.findOneAndUpdate(searchParameter, updatePullData, { const agentAfterPull = await Agent.findOneAndUpdate(searchParameter, updatePullData, {
new: true, new: true,
}).lean(); }).lean();
@ -458,7 +455,7 @@ const removeAgentResourceFiles = async ({ agent_id, files }) => {
* @returns {Promise<void>} Resolves when the agent has been successfully deleted. * @returns {Promise<void>} Resolves when the agent has been successfully deleted.
*/ */
const deleteAgent = async (searchParameter) => { const deleteAgent = async (searchParameter) => {
const agent = await db.models.Agent.findOneAndDelete(searchParameter); const agent = await Agent.findOneAndDelete(searchParameter);
if (agent) { if (agent) {
await removeAgentFromAllProjects(agent.id); await removeAgentFromAllProjects(agent.id);
} }
@ -483,7 +480,7 @@ const getListAgents = async (searchParameter) => {
query = { $or: [globalQuery, query] }; query = { $or: [globalQuery, query] };
} }
const agents = ( const agents = (
await db.models.Agent.find(query, { await Agent.find(query, {
id: 1, id: 1,
_id: 0, _id: 0,
name: 1, name: 1,
@ -580,7 +577,6 @@ const updateAgentProjects = async ({ user, agentId, projectIds, removeProjectIds
* @throws {Error} If the agent is not found or the specified version does not exist. * @throws {Error} If the agent is not found or the specified version does not exist.
*/ */
const revertAgentVersion = async (searchParameter, versionIndex) => { const revertAgentVersion = async (searchParameter, versionIndex) => {
const Agent = db.models?.Agent;
const agent = await Agent.findOne(searchParameter); const agent = await Agent.findOne(searchParameter);
if (!agent) { if (!agent) {
throw new Error('Agent not found'); throw new Error('Agent not found');

View file

@ -8,6 +8,7 @@ process.env.CREDS_IV = '0123456789abcdef';
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { v4: uuidv4 } = require('uuid'); const { v4: uuidv4 } = require('uuid');
const { Agent } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server'); const { MongoMemoryServer } = require('mongodb-memory-server');
const { const {
addAgentResourceFile, addAgentResourceFile,
@ -19,9 +20,6 @@ const {
getListAgents, getListAgents,
updateAgentProjects, updateAgentProjects,
} = require('./Agent'); } = require('./Agent');
const db = require('~/lib/db/connectDb');
let Agent;
describe('Agent Resource File Operations', () => { describe('Agent Resource File Operations', () => {
let mongoServer; let mongoServer;
@ -29,9 +27,7 @@ describe('Agent Resource File Operations', () => {
beforeAll(async () => { beforeAll(async () => {
mongoServer = await MongoMemoryServer.create(); mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri(); const mongoUri = mongoServer.getUri();
await db.connectDb(mongoUri); await mongoose.connect(mongoUri);
Agent = db.models.Agent;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,4 +1,4 @@
const db = require('~/lib/db/connectDb'); const { Assistant } = require('@librechat/data-schemas');
/** /**
* Update an assistant with new data without overwriting existing properties, * Update an assistant with new data without overwriting existing properties,
@ -12,7 +12,7 @@ const db = require('~/lib/db/connectDb');
*/ */
const updateAssistantDoc = async (searchParams, updateData) => { const updateAssistantDoc = async (searchParams, updateData) => {
const options = { new: true, upsert: true }; const options = { new: true, upsert: true };
return await db.models.Assistant.findOneAndUpdate(searchParams, updateData, options).lean(); return await Assistant.findOneAndUpdate(searchParams, updateData, options).lean();
}; };
/** /**
@ -23,7 +23,7 @@ const updateAssistantDoc = async (searchParams, updateData) => {
* @param {string} searchParams.user - The user ID of the assistant's author. * @param {string} searchParams.user - The user ID of the assistant's author.
* @returns {Promise<AssistantDocument|null>} The assistant document as a plain object, or null if not found. * @returns {Promise<AssistantDocument|null>} The assistant document as a plain object, or null if not found.
*/ */
const getAssistant = async (searchParams) => await db.models.Assistant.findOne(searchParams).lean(); const getAssistant = async (searchParams) => await Assistant.findOne(searchParams).lean();
/** /**
* Retrieves all assistants that match the given search parameters. * Retrieves all assistants that match the given search parameters.
@ -33,7 +33,7 @@ const getAssistant = async (searchParams) => await db.models.Assistant.findOne(s
* @returns {Promise<Array<AssistantDocument>>} A promise that resolves to an array of assistant documents as plain objects. * @returns {Promise<Array<AssistantDocument>>} A promise that resolves to an array of assistant documents as plain objects.
*/ */
const getAssistants = async (searchParams, select = null) => { const getAssistants = async (searchParams, select = null) => {
let query = db.models.Assistant.find(searchParams); let query = Assistant.find(searchParams);
if (select) { if (select) {
query = query.select(select); query = query.select(select);
@ -51,7 +51,7 @@ const getAssistants = async (searchParams, select = null) => {
* @returns {Promise<void>} Resolves when the assistant has been successfully deleted. * @returns {Promise<void>} Resolves when the assistant has been successfully deleted.
*/ */
const deleteAssistant = async (searchParams) => { const deleteAssistant = async (searchParams) => {
return await db.models.Assistant.findOneAndDelete(searchParams); return await Assistant.findOneAndDelete(searchParams);
}; };
module.exports = { module.exports = {

View file

@ -1,5 +1,4 @@
const logger = require('~/config/winston'); const { Banner, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
/** /**
* Retrieves the current active banner. * Retrieves the current active banner.
@ -8,7 +7,7 @@ const db = require('~/lib/db/connectDb');
const getBanner = async (user) => { const getBanner = async (user) => {
try { try {
const now = new Date(); const now = new Date();
const banner = await db.models.Banner.findOne({ const banner = await Banner.findOne({
displayFrom: { $lte: now }, displayFrom: { $lte: now },
$or: [{ displayTo: { $gte: now } }, { displayTo: null }], $or: [{ displayTo: { $gte: now } }, { displayTo: null }],
type: 'banner', type: 'banner',

View file

@ -1,6 +1,5 @@
const { Conversation, logger } = require('@librechat/data-schemas');
const { getMessages, deleteMessages } = require('./Message'); const { getMessages, deleteMessages } = require('./Message');
const logger = require('~/config/winston');
const db = require('~/lib/db/connectDb');
/** /**
* Searches for a conversation by conversationId and returns a lean document with only conversationId and user. * Searches for a conversation by conversationId and returns a lean document with only conversationId and user.
* @param {string} conversationId - The conversation's ID. * @param {string} conversationId - The conversation's ID.
@ -8,7 +7,7 @@ const db = require('~/lib/db/connectDb');
*/ */
const searchConversation = async (conversationId) => { const searchConversation = async (conversationId) => {
try { try {
return await db.models.Conversation.findOne({ conversationId }, 'conversationId user').lean(); return await Conversation.findOne({ conversationId }, 'conversationId user').lean();
} catch (error) { } catch (error) {
logger.error('[searchConversation] Error searching conversation', error); logger.error('[searchConversation] Error searching conversation', error);
throw new Error('Error searching conversation'); throw new Error('Error searching conversation');
@ -23,7 +22,7 @@ const searchConversation = async (conversationId) => {
*/ */
const getConvo = async (user, conversationId) => { const getConvo = async (user, conversationId) => {
try { try {
return await db.models.Conversation.findOne({ user, conversationId }).lean(); return await Conversation.findOne({ user, conversationId }).lean();
} catch (error) { } catch (error) {
logger.error('[getConvo] Error getting single conversation', error); logger.error('[getConvo] Error getting single conversation', error);
return { message: 'Error getting single conversation' }; return { message: 'Error getting single conversation' };
@ -40,7 +39,7 @@ const deleteNullOrEmptyConversations = async () => {
], ],
}; };
const result = await db.models.Conversation.deleteMany(filter); const result = await Conversation.deleteMany(filter);
// Delete associated messages // Delete associated messages
const messageDeleteResult = await deleteMessages(filter); const messageDeleteResult = await deleteMessages(filter);
@ -66,7 +65,7 @@ const deleteNullOrEmptyConversations = async () => {
*/ */
const getConvoFiles = async (conversationId) => { const getConvoFiles = async (conversationId) => {
try { try {
return (await db.models.Conversation.findOne({ conversationId }, 'files').lean())?.files ?? []; return (await Conversation.findOne({ conversationId }, 'files').lean())?.files ?? [];
} catch (error) { } catch (error) {
logger.error('[getConvoFiles] Error getting conversation files', error); logger.error('[getConvoFiles] Error getting conversation files', error);
throw new Error('Error getting conversation files'); throw new Error('Error getting conversation files');
@ -112,7 +111,7 @@ module.exports = {
} }
/** Note: the resulting Model object is necessary for Meilisearch operations */ /** Note: the resulting Model object is necessary for Meilisearch operations */
const conversation = await db.models.Conversation.findOneAndUpdate( const conversation = await Conversation.findOneAndUpdate(
{ conversationId, user: req.user.id }, { conversationId, user: req.user.id },
updateOperation, updateOperation,
{ {
@ -141,7 +140,7 @@ module.exports = {
}, },
})); }));
const result = await db.models.Conversation.bulkWrite(bulkOps); const result = await Conversation.bulkWrite(bulkOps);
return result; return result;
} catch (error) { } catch (error) {
logger.error('[saveBulkConversations] Error saving conversations in bulk', error); logger.error('[saveBulkConversations] Error saving conversations in bulk', error);
@ -153,7 +152,6 @@ module.exports = {
{ cursor, limit = 25, isArchived = false, tags, search, order = 'desc' } = {}, { cursor, limit = 25, isArchived = false, tags, search, order = 'desc' } = {},
) => { ) => {
const filters = [{ user }]; const filters = [{ user }];
const { Conversation } = db.models;
if (isArchived) { if (isArchived) {
filters.push({ isArchived: true }); filters.push({ isArchived: true });
} else { } else {
@ -217,7 +215,7 @@ module.exports = {
const conversationIds = convoIds.map((convo) => convo.conversationId); const conversationIds = convoIds.map((convo) => convo.conversationId);
const results = await db.models.Conversation.find({ const results = await Conversation.find({
user, user,
conversationId: { $in: conversationIds }, conversationId: { $in: conversationIds },
$or: [{ expiredAt: { $exists: false } }, { expiredAt: null }], $or: [{ expiredAt: { $exists: false } }, { expiredAt: null }],
@ -286,7 +284,6 @@ module.exports = {
deleteConvos: async (user, filter) => { deleteConvos: async (user, filter) => {
try { try {
const userFilter = { ...filter, user }; const userFilter = { ...filter, user };
const { Conversation } = db.models;
const conversations = await Conversation.find(userFilter).select('conversationId'); const conversations = await Conversation.find(userFilter).select('conversationId');
const conversationIds = conversations.map((c) => c.conversationId); const conversationIds = conversations.map((c) => c.conversationId);

View file

@ -1,5 +1,4 @@
const logger = require('~/config/winston'); const { ConversationTag, Conversation, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
/** /**
* Retrieves all conversation tags for a user. * Retrieves all conversation tags for a user.
@ -8,7 +7,7 @@ const db = require('~/lib/db/connectDb');
*/ */
const getConversationTags = async (user) => { const getConversationTags = async (user) => {
try { try {
return await db.models.ConversationTag.find({ user }).sort({ position: 1 }).lean(); return await ConversationTag.find({ user }).sort({ position: 1 }).lean();
} catch (error) { } catch (error) {
logger.error('[getConversationTags] Error getting conversation tags', error); logger.error('[getConversationTags] Error getting conversation tags', error);
throw new Error('Error getting conversation tags'); throw new Error('Error getting conversation tags');
@ -29,7 +28,6 @@ const createConversationTag = async (user, data) => {
try { try {
const { tag, description, addToConversation, conversationId } = data; const { tag, description, addToConversation, conversationId } = data;
const { ConversationTag, Conversation } = db.models;
const existingTag = await ConversationTag.findOne({ user, tag }).lean(); const existingTag = await ConversationTag.findOne({ user, tag }).lean();
if (existingTag) { if (existingTag) {
return existingTag; return existingTag;
@ -84,7 +82,6 @@ const updateConversationTag = async (user, oldTag, data) => {
try { try {
const { tag: newTag, description, position } = data; const { tag: newTag, description, position } = data;
const { ConversationTag, Conversation } = db.models;
const existingTag = await ConversationTag.findOne({ user, tag: oldTag }).lean(); const existingTag = await ConversationTag.findOne({ user, tag: oldTag }).lean();
if (!existingTag) { if (!existingTag) {
return null; return null;
@ -145,7 +142,7 @@ const adjustPositions = async (user, oldPosition, newPosition) => {
$lt: Math.max(oldPosition, newPosition), $lt: Math.max(oldPosition, newPosition),
}; };
await db.models.ConversationTag.updateMany( await ConversationTag.updateMany(
{ {
user, user,
position, position,
@ -162,7 +159,6 @@ const adjustPositions = async (user, oldPosition, newPosition) => {
*/ */
const deleteConversationTag = async (user, tag) => { const deleteConversationTag = async (user, tag) => {
try { try {
const { ConversationTag, Conversation } = db.models;
const deletedTag = await ConversationTag.findOneAndDelete({ user, tag }).lean(); const deletedTag = await ConversationTag.findOneAndDelete({ user, tag }).lean();
if (!deletedTag) { if (!deletedTag) {
return null; return null;
@ -191,7 +187,6 @@ const deleteConversationTag = async (user, tag) => {
*/ */
const updateTagsForConversation = async (user, conversationId, tags) => { const updateTagsForConversation = async (user, conversationId, tags) => {
try { try {
const { ConversationTag, Conversation } = db.models;
const conversation = await Conversation.findOne({ user, conversationId }).lean(); const conversation = await Conversation.findOne({ user, conversationId }).lean();
if (!conversation) { if (!conversation) {
throw new Error('Conversation not found'); throw new Error('Conversation not found');

View file

@ -1,7 +1,7 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { File } = require('@librechat/data-schemas');
const { EToolResources } = require('librechat-data-provider'); const { EToolResources } = require('librechat-data-provider');
const { logger } = require('~/config'); const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/** /**
* Finds a file by its file_id with additional query options. * Finds a file by its file_id with additional query options.
@ -10,7 +10,7 @@ const db = require('~/lib/db/connectDb');
* @returns {Promise<MongoFile>} A promise that resolves to the file document or null. * @returns {Promise<MongoFile>} A promise that resolves to the file document or null.
*/ */
const findFileById = async (file_id, options = {}) => { const findFileById = async (file_id, options = {}) => {
return await db.models.File.findOne({ file_id, ...options }).lean(); return await File.findOne({ file_id, ...options }).lean();
}; };
/** /**
@ -23,7 +23,7 @@ const findFileById = async (file_id, options = {}) => {
*/ */
const getFiles = async (filter, _sortOptions, selectFields = { text: 0 }) => { const getFiles = async (filter, _sortOptions, selectFields = { text: 0 }) => {
const sortOptions = { updatedAt: -1, ..._sortOptions }; const sortOptions = { updatedAt: -1, ..._sortOptions };
return await db.models.File.find(filter).select(selectFields).sort(sortOptions).lean(); return await File.find(filter).select(selectFields).sort(sortOptions).lean();
}; };
/** /**
@ -79,7 +79,7 @@ const createFile = async (data, disableTTL) => {
delete fileData.expiresAt; delete fileData.expiresAt;
} }
return await db.models.File.findOneAndUpdate({ file_id: data.file_id }, fileData, { return await File.findOneAndUpdate({ file_id: data.file_id }, fileData, {
new: true, new: true,
upsert: true, upsert: true,
}).lean(); }).lean();
@ -96,7 +96,7 @@ const updateFile = async (data) => {
$set: update, $set: update,
$unset: { expiresAt: '' }, // Remove the expiresAt field to prevent TTL $unset: { expiresAt: '' }, // Remove the expiresAt field to prevent TTL
}; };
return await db.models.File.findOneAndUpdate({ file_id }, updateOperation, { new: true }).lean(); return await File.findOneAndUpdate({ file_id }, updateOperation, { new: true }).lean();
}; };
/** /**
@ -110,7 +110,7 @@ const updateFileUsage = async (data) => {
$inc: { usage: inc }, $inc: { usage: inc },
$unset: { expiresAt: '', temp_file_id: '' }, $unset: { expiresAt: '', temp_file_id: '' },
}; };
return await db.models.File.findOneAndUpdate({ file_id }, updateOperation, { new: true }).lean(); return await File.findOneAndUpdate({ file_id }, updateOperation, { new: true }).lean();
}; };
/** /**
@ -119,7 +119,7 @@ const updateFileUsage = async (data) => {
* @returns {Promise<MongoFile>} A promise that resolves to the deleted file document or null. * @returns {Promise<MongoFile>} A promise that resolves to the deleted file document or null.
*/ */
const deleteFile = async (file_id) => { const deleteFile = async (file_id) => {
return await db.models.File.findOneAndDelete({ file_id }).lean(); return await File.findOneAndDelete({ file_id }).lean();
}; };
/** /**
@ -128,7 +128,7 @@ const deleteFile = async (file_id) => {
* @returns {Promise<MongoFile>} A promise that resolves to the deleted file document or null. * @returns {Promise<MongoFile>} A promise that resolves to the deleted file document or null.
*/ */
const deleteFileByFilter = async (filter) => { const deleteFileByFilter = async (filter) => {
return await db.models.File.findOneAndDelete(filter).lean(); return await File.findOneAndDelete(filter).lean();
}; };
/** /**
@ -141,7 +141,7 @@ const deleteFiles = async (file_ids, user) => {
if (user) { if (user) {
deleteQuery = { user: user }; deleteQuery = { user: user };
} }
return await db.models.File.deleteMany(deleteQuery); return await File.deleteMany(deleteQuery);
}; };
/** /**

View file

@ -1,6 +1,5 @@
const { z } = require('zod'); const { z } = require('zod');
const { logger } = require('~/config'); const { Message, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
const idSchema = z.string().uuid(); const idSchema = z.string().uuid();
/** /**
@ -67,7 +66,7 @@ async function saveMessage(req, params, metadata) {
logger.info(`---\`saveMessage\` context: ${metadata?.context}`); logger.info(`---\`saveMessage\` context: ${metadata?.context}`);
update.tokenCount = 0; update.tokenCount = 0;
} }
const message = await db.models.Message.findOneAndUpdate( const message = await Message.findOneAndUpdate(
{ messageId: params.messageId, user: req.user.id }, { messageId: params.messageId, user: req.user.id },
update, update,
{ upsert: true, new: true }, { upsert: true, new: true },
@ -85,7 +84,7 @@ async function saveMessage(req, params, metadata) {
try { try {
// Try to find the existing message with this ID // Try to find the existing message with this ID
const existingMessage = await db.models.Message.findOne({ const existingMessage = await Message.findOne({
messageId: params.messageId, messageId: params.messageId,
user: req.user.id, user: req.user.id,
}); });
@ -138,7 +137,7 @@ async function bulkSaveMessages(messages, overrideTimestamp = false) {
upsert: true, upsert: true,
}, },
})); }));
const result = await db.models.Message.bulkWrite(bulkOps); const result = await Message.bulkWrite(bulkOps);
return result; return result;
} catch (err) { } catch (err) {
logger.error('Error saving messages in bulk:', err); logger.error('Error saving messages in bulk:', err);
@ -180,7 +179,7 @@ async function recordMessage({
...rest, ...rest,
}; };
return await db.models.Message.findOneAndUpdate({ user, messageId }, message, { return await Message.findOneAndUpdate({ user, messageId }, message, {
upsert: true, upsert: true,
new: true, new: true,
}); });
@ -204,7 +203,7 @@ async function recordMessage({
*/ */
async function updateMessageText(req, { messageId, text }) { async function updateMessageText(req, { messageId, text }) {
try { try {
await db.models?.Message.updateOne({ messageId, user: req.user.id }, { text }); await Message.updateOne({ messageId, user: req.user.id }, { text });
} catch (err) { } catch (err) {
logger.error('Error updating message text:', err); logger.error('Error updating message text:', err);
throw err; throw err;
@ -232,7 +231,7 @@ async function updateMessageText(req, { messageId, text }) {
async function updateMessage(req, message, metadata) { async function updateMessage(req, message, metadata) {
try { try {
const { messageId, ...update } = message; const { messageId, ...update } = message;
const updatedMessage = await db.models.Message.findOneAndUpdate( const updatedMessage = await Message.findOneAndUpdate(
{ messageId, user: req.user.id }, { messageId, user: req.user.id },
update, update,
{ {
@ -276,10 +275,10 @@ async function updateMessage(req, message, metadata) {
*/ */
async function deleteMessagesSince(req, { messageId, conversationId }) { async function deleteMessagesSince(req, { messageId, conversationId }) {
try { try {
const message = await db.models.Message.findOne({ messageId, user: req.user.id }).lean(); const message = await Message.findOne({ messageId, user: req.user.id }).lean();
if (message) { if (message) {
const query = db.models.Message.find({ conversationId, user: req.user.id }); const query = Message.find({ conversationId, user: req.user.id });
return await query.deleteMany({ return await query.deleteMany({
createdAt: { $gt: message.createdAt }, createdAt: { $gt: message.createdAt },
}); });
@ -303,10 +302,10 @@ async function deleteMessagesSince(req, { messageId, conversationId }) {
async function getMessages(filter, select) { async function getMessages(filter, select) {
try { try {
if (select) { if (select) {
return await db.models.Message.find(filter).select(select).sort({ createdAt: 1 }).lean(); return await Message.find(filter).select(select).sort({ createdAt: 1 }).lean();
} }
return await db.models.Message.find(filter).sort({ createdAt: 1 }).lean(); return await Message.find(filter).sort({ createdAt: 1 }).lean();
} catch (err) { } catch (err) {
logger.error('Error getting messages:', err); logger.error('Error getting messages:', err);
throw err; throw err;
@ -323,7 +322,7 @@ async function getMessages(filter, select) {
*/ */
async function getMessage({ user, messageId }) { async function getMessage({ user, messageId }) {
try { try {
return await db.models.Message.findOne({ return await Message.findOne({
user, user,
messageId, messageId,
}).lean(); }).lean();
@ -344,7 +343,7 @@ async function getMessage({ user, messageId }) {
*/ */
async function deleteMessages(filter) { async function deleteMessages(filter) {
try { try {
return await db.models.Message.deleteMany(filter); return await Message.deleteMany(filter);
} catch (err) { } catch (err) {
logger.error('Error deleting messages:', err); logger.error('Error deleting messages:', err);
throw err; throw err;

View file

@ -1,9 +1,8 @@
const { logger } = require('~/config'); const { Preset, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
const getPreset = async (user, presetId) => { const getPreset = async (user, presetId) => {
try { try {
return await db.models.Preset.findOne({ user, presetId }).lean(); return await Preset.findOne({ user, presetId }).lean();
} catch (error) { } catch (error) {
logger.error('[getPreset] Error getting single preset', error); logger.error('[getPreset] Error getting single preset', error);
return { message: 'Error getting single preset' }; return { message: 'Error getting single preset' };
@ -14,7 +13,7 @@ module.exports = {
getPreset, getPreset,
getPresets: async (user, filter) => { getPresets: async (user, filter) => {
try { try {
const presets = await db.models.Preset.find({ ...filter, user }).lean(); const presets = await Preset.find({ ...filter, user }).lean();
const defaultValue = 10000; const defaultValue = 10000;
presets.sort((a, b) => { presets.sort((a, b) => {
@ -39,7 +38,6 @@ module.exports = {
const setter = { $set: {} }; const setter = { $set: {} };
const { user: _, ...cleanPreset } = preset; const { user: _, ...cleanPreset } = preset;
const update = { presetId, ...cleanPreset }; const update = { presetId, ...cleanPreset };
const Preset = db.models.Preset;
if (preset.tools && Array.isArray(preset.tools)) { if (preset.tools && Array.isArray(preset.tools)) {
update.tools = update.tools =
preset.tools preset.tools
@ -77,7 +75,7 @@ module.exports = {
deletePresets: async (user, filter) => { deletePresets: async (user, filter) => {
// let toRemove = await Preset.find({ ...filter, user }).select('presetId'); // let toRemove = await Preset.find({ ...filter, user }).select('presetId');
// const ids = toRemove.map((instance) => instance.presetId); // const ids = toRemove.map((instance) => instance.presetId);
let deleteCount = await db.models.Preset.deleteMany({ ...filter, user }); let deleteCount = await Preset.deleteMany({ ...filter, user });
return deleteCount; return deleteCount;
}, },
}; };

View file

@ -1,5 +1,5 @@
const { Project } = require('@librechat/data-schemas');
const { GLOBAL_PROJECT_NAME } = require('librechat-data-provider').Constants; const { GLOBAL_PROJECT_NAME } = require('librechat-data-provider').Constants;
const db = require('~/lib/db/connectDb');
/** /**
* Retrieve a project by ID and convert the found project document to a plain object. * Retrieve a project by ID and convert the found project document to a plain object.
@ -9,7 +9,7 @@ const db = require('~/lib/db/connectDb');
* @returns {Promise<IMongoProject>} A plain object representing the project document, or `null` if no project is found. * @returns {Promise<IMongoProject>} A plain object representing the project document, or `null` if no project is found.
*/ */
const getProjectById = async function (projectId, fieldsToSelect = null) { const getProjectById = async function (projectId, fieldsToSelect = null) {
const query = db.models.Project.findById(projectId); const query = Project.findById(projectId);
if (fieldsToSelect) { if (fieldsToSelect) {
query.select(fieldsToSelect); query.select(fieldsToSelect);
@ -36,7 +36,7 @@ const getProjectByName = async function (projectName, fieldsToSelect = null) {
select: fieldsToSelect, select: fieldsToSelect,
}; };
return await db.models.Project.findOneAndUpdate(query, update, options); return await Project.findOneAndUpdate(query, update, options);
}; };
/** /**
@ -47,7 +47,7 @@ const getProjectByName = async function (projectName, fieldsToSelect = null) {
* @returns {Promise<IMongoProject>} The updated project document. * @returns {Promise<IMongoProject>} The updated project document.
*/ */
const addGroupIdsToProject = async function (projectId, promptGroupIds) { const addGroupIdsToProject = async function (projectId, promptGroupIds) {
return await db.models.Project.findByIdAndUpdate( return await Project.findByIdAndUpdate(
projectId, projectId,
{ $addToSet: { promptGroupIds: { $each: promptGroupIds } } }, { $addToSet: { promptGroupIds: { $each: promptGroupIds } } },
{ new: true }, { new: true },
@ -62,7 +62,7 @@ const addGroupIdsToProject = async function (projectId, promptGroupIds) {
* @returns {Promise<IMongoProject>} The updated project document. * @returns {Promise<IMongoProject>} The updated project document.
*/ */
const removeGroupIdsFromProject = async function (projectId, promptGroupIds) { const removeGroupIdsFromProject = async function (projectId, promptGroupIds) {
return await db.models.Project.findByIdAndUpdate( return await Project.findByIdAndUpdate(
projectId, projectId,
{ $pull: { promptGroupIds: { $in: promptGroupIds } } }, { $pull: { promptGroupIds: { $in: promptGroupIds } } },
{ new: true }, { new: true },
@ -76,7 +76,7 @@ const removeGroupIdsFromProject = async function (projectId, promptGroupIds) {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
const removeGroupFromAllProjects = async (promptGroupId) => { const removeGroupFromAllProjects = async (promptGroupId) => {
await db.models.Project.updateMany({}, { $pull: { promptGroupIds: promptGroupId } }); await Project.updateMany({}, { $pull: { promptGroupIds: promptGroupId } });
}; };
/** /**
@ -87,7 +87,7 @@ const removeGroupFromAllProjects = async (promptGroupId) => {
* @returns {Promise<IMongoProject>} The updated project document. * @returns {Promise<IMongoProject>} The updated project document.
*/ */
const addAgentIdsToProject = async function (projectId, agentIds) { const addAgentIdsToProject = async function (projectId, agentIds) {
return await db.models.Project.findByIdAndUpdate( return await Project.findByIdAndUpdate(
projectId, projectId,
{ $addToSet: { agentIds: { $each: agentIds } } }, { $addToSet: { agentIds: { $each: agentIds } } },
{ new: true }, { new: true },
@ -102,7 +102,7 @@ const addAgentIdsToProject = async function (projectId, agentIds) {
* @returns {Promise<IMongoProject>} The updated project document. * @returns {Promise<IMongoProject>} The updated project document.
*/ */
const removeAgentIdsFromProject = async function (projectId, agentIds) { const removeAgentIdsFromProject = async function (projectId, agentIds) {
return await db.models.Project.findByIdAndUpdate( return await Project.findByIdAndUpdate(
projectId, projectId,
{ $pull: { agentIds: { $in: agentIds } } }, { $pull: { agentIds: { $in: agentIds } } },
{ new: true }, { new: true },
@ -116,7 +116,7 @@ const removeAgentIdsFromProject = async function (projectId, agentIds) {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
const removeAgentFromAllProjects = async (agentId) => { const removeAgentFromAllProjects = async (agentId) => {
await db.models.Project.updateMany({}, { $pull: { agentIds: agentId } }); await Project.updateMany({}, { $pull: { agentIds: agentId } });
}; };
module.exports = { module.exports = {

View file

@ -1,4 +1,5 @@
const { ObjectId } = require('mongodb'); const { ObjectId } = require('mongodb');
const { Prompt, PromptGroup, logger } = require('@librechat/data-schemas');
const { SystemRoles, SystemCategories, Constants } = require('librechat-data-provider'); const { SystemRoles, SystemCategories, Constants } = require('librechat-data-provider');
const { const {
getProjectByName, getProjectByName,
@ -7,8 +8,6 @@ const {
removeGroupFromAllProjects, removeGroupFromAllProjects,
} = require('./Project'); } = require('./Project');
const { escapeRegExp } = require('~/server/utils'); const { escapeRegExp } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/** /**
* Create a pipeline for the aggregation to get prompt groups * Create a pipeline for the aggregation to get prompt groups
@ -133,7 +132,7 @@ const getAllPromptGroups = async (req, filter) => {
} }
const promptGroupsPipeline = createAllGroupsPipeline(combinedQuery); const promptGroupsPipeline = createAllGroupsPipeline(combinedQuery);
return await db.models.PromptGroup.aggregate(promptGroupsPipeline).exec(); return await PromptGroup.aggregate(promptGroupsPipeline).exec();
} catch (error) { } catch (error) {
console.error('Error getting all prompt groups', error); console.error('Error getting all prompt groups', error);
return { message: 'Error getting all prompt groups' }; return { message: 'Error getting all prompt groups' };
@ -233,7 +232,7 @@ const deletePromptGroup = async ({ _id, author, role }) => {
throw new Error('Prompt group not found'); throw new Error('Prompt group not found');
} }
await db.models.Prompt.deleteMany(groupQuery); await Prompt.deleteMany(groupQuery);
await removeGroupFromAllProjects(_id); await removeGroupFromAllProjects(_id);
return { message: 'Prompt group deleted successfully' }; return { message: 'Prompt group deleted successfully' };
}; };
@ -250,7 +249,6 @@ module.exports = {
createPromptGroup: async (saveData) => { createPromptGroup: async (saveData) => {
try { try {
const { prompt, group, author, authorName } = saveData; const { prompt, group, author, authorName } = saveData;
const { Prompt, PromptGroup } = db.models;
let newPromptGroup = await PromptGroup.findOneAndUpdate( let newPromptGroup = await PromptGroup.findOneAndUpdate(
{ ...group, author, authorName, productionId: null }, { ...group, author, authorName, productionId: null },
@ -306,7 +304,6 @@ module.exports = {
/** @type {TPrompt} */ /** @type {TPrompt} */
let newPrompt; let newPrompt;
const { Prompt } = db.models;
try { try {
newPrompt = await Prompt.create(newPromptData); newPrompt = await Prompt.create(newPromptData);
} catch (error) { } catch (error) {
@ -326,7 +323,7 @@ module.exports = {
}, },
getPrompts: async (filter) => { getPrompts: async (filter) => {
try { try {
return await db.models.Prompt.find(filter).sort({ createdAt: -1 }).lean(); return await Prompt.find(filter).sort({ createdAt: -1 }).lean();
} catch (error) { } catch (error) {
logger.error('Error getting prompts', error); logger.error('Error getting prompts', error);
return { message: 'Error getting prompts' }; return { message: 'Error getting prompts' };
@ -337,7 +334,7 @@ module.exports = {
if (filter.groupId) { if (filter.groupId) {
filter.groupId = new ObjectId(filter.groupId); filter.groupId = new ObjectId(filter.groupId);
} }
return await db.models.Prompt.findOne(filter).lean(); return await Prompt.findOne(filter).lean();
} catch (error) { } catch (error) {
logger.error('Error getting prompt', error); logger.error('Error getting prompt', error);
return { message: 'Error getting prompt' }; return { message: 'Error getting prompt' };
@ -350,7 +347,7 @@ module.exports = {
*/ */
getRandomPromptGroups: async (filter) => { getRandomPromptGroups: async (filter) => {
try { try {
const result = await db.models.PromptGroup.aggregate([ const result = await PromptGroup.aggregate([
{ {
$match: { $match: {
category: { $ne: '' }, category: { $ne: '' },
@ -383,7 +380,7 @@ module.exports = {
}, },
getPromptGroupsWithPrompts: async (filter) => { getPromptGroupsWithPrompts: async (filter) => {
try { try {
return await db.models.PromptGroup.findOne(filter) return await PromptGroup.findOne(filter)
.populate({ .populate({
path: 'prompts', path: 'prompts',
select: '-_id -__v -user', select: '-_id -__v -user',
@ -397,7 +394,7 @@ module.exports = {
}, },
getPromptGroup: async (filter) => { getPromptGroup: async (filter) => {
try { try {
return await db.models.PromptGroup.findOne(filter).lean(); return await PromptGroup.findOne(filter).lean();
} catch (error) { } catch (error) {
logger.error('Error getting prompt group', error); logger.error('Error getting prompt group', error);
return { message: 'Error getting prompt group' }; return { message: 'Error getting prompt group' };
@ -418,7 +415,6 @@ module.exports = {
*/ */
deletePrompt: async ({ promptId, groupId, author, role }) => { deletePrompt: async ({ promptId, groupId, author, role }) => {
const query = { _id: promptId, groupId, author }; const query = { _id: promptId, groupId, author };
const { Prompt, PromptGroup } = db.models;
if (role === SystemRoles.ADMIN) { if (role === SystemRoles.ADMIN) {
delete query.author; delete query.author;
} }
@ -483,7 +479,7 @@ module.exports = {
} }
const updateData = { ...data, ...updateOps }; const updateData = { ...data, ...updateOps };
const updatedDoc = await db.models.PromptGroup.findOneAndUpdate(filter, updateData, { const updatedDoc = await PromptGroup.findOneAndUpdate(filter, updateData, {
new: true, new: true,
upsert: false, upsert: false,
}); });
@ -505,7 +501,6 @@ module.exports = {
*/ */
makePromptProduction: async (promptId) => { makePromptProduction: async (promptId) => {
try { try {
const { Prompt, PromptGroup } = db.models;
const prompt = await Prompt.findById(promptId).lean(); const prompt = await Prompt.findById(promptId).lean();
if (!prompt) { if (!prompt) {
@ -530,7 +525,7 @@ module.exports = {
}, },
updatePromptLabels: async (_id, labels) => { updatePromptLabels: async (_id, labels) => {
try { try {
const response = await db.models.Prompt.updateOne({ _id }, { $set: { labels } }); const response = await Prompt.updateOne({ _id }, { $set: { labels } });
if (response.matchedCount === 0) { if (response.matchedCount === 0) {
return { message: 'Prompt not found' }; return { message: 'Prompt not found' };
} }

View file

@ -6,9 +6,8 @@ const {
permissionsSchema, permissionsSchema,
removeNullishValues, removeNullishValues,
} = require('librechat-data-provider'); } = require('librechat-data-provider');
const { Role, logger } = require('@librechat/data-schemas');
const getLogStores = require('~/cache/getLogStores'); const getLogStores = require('~/cache/getLogStores');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/** /**
* Retrieve a role by name and convert the found role document to a plain object. * Retrieve a role by name and convert the found role document to a plain object.
@ -21,7 +20,6 @@ const db = require('~/lib/db/connectDb');
*/ */
const getRoleByName = async function (roleName, fieldsToSelect = null) { const getRoleByName = async function (roleName, fieldsToSelect = null) {
const cache = getLogStores(CacheKeys.ROLES); const cache = getLogStores(CacheKeys.ROLES);
const { Role } = db.models;
try { try {
const cachedRole = await cache.get(roleName); const cachedRole = await cache.get(roleName);
if (cachedRole) { if (cachedRole) {
@ -55,7 +53,7 @@ const getRoleByName = async function (roleName, fieldsToSelect = null) {
const updateRoleByName = async function (roleName, updates) { const updateRoleByName = async function (roleName, updates) {
const cache = getLogStores(CacheKeys.ROLES); const cache = getLogStores(CacheKeys.ROLES);
try { try {
const role = await db.models.Role.findOneAndUpdate( const role = await Role.findOneAndUpdate(
{ name: roleName }, { name: roleName },
{ $set: updates }, { $set: updates },
{ new: true, lean: true }, { new: true, lean: true },
@ -76,7 +74,6 @@ const updateRoleByName = async function (roleName, updates) {
* @param {Object.<PermissionTypes, Object.<Permissions, boolean>>} permissionsUpdate - Permissions to update and their values. * @param {Object.<PermissionTypes, Object.<Permissions, boolean>>} permissionsUpdate - Permissions to update and their values.
*/ */
async function updateAccessPermissions(roleName, permissionsUpdate) { async function updateAccessPermissions(roleName, permissionsUpdate) {
const { Role } = db.models;
// Filter and clean the permission updates based on our schema definition. // Filter and clean the permission updates based on our schema definition.
const updates = {}; const updates = {};
for (const [permissionType, permissions] of Object.entries(permissionsUpdate)) { for (const [permissionType, permissions] of Object.entries(permissionsUpdate)) {
@ -180,7 +177,6 @@ async function updateAccessPermissions(roleName, permissionsUpdate) {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
const initializeRoles = async function () { const initializeRoles = async function () {
const { Role } = db.models;
for (const roleName of [SystemRoles.ADMIN, SystemRoles.USER]) { for (const roleName of [SystemRoles.ADMIN, SystemRoles.USER]) {
let role = await Role.findOne({ name: roleName }); let role = await Role.findOne({ name: roleName });
const defaultPerms = roleDefaults[roleName].permissions; const defaultPerms = roleDefaults[roleName].permissions;
@ -210,7 +206,6 @@ const initializeRoles = async function () {
* @returns {Promise<number>} Number of roles migrated. * @returns {Promise<number>} Number of roles migrated.
*/ */
const migrateRoleSchema = async function (roleName) { const migrateRoleSchema = async function (roleName) {
const { Role } = db.models;
try { try {
// Get roles to migrate // Get roles to migrate
let roles; let roles;

View file

@ -1,4 +1,5 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { Role, logger } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server'); const { MongoMemoryServer } = require('mongodb-memory-server');
const { const {
SystemRoles, SystemRoles,
@ -9,8 +10,6 @@ const {
const { getRoleByName, updateAccessPermissions, initializeRoles } = require('~/models/Role'); const { getRoleByName, updateAccessPermissions, initializeRoles } = require('~/models/Role');
const getLogStores = require('~/cache/getLogStores'); const getLogStores = require('~/cache/getLogStores');
const db = require('~/lib/db/connectDb');
// Mock the cache // Mock the cache
jest.mock('~/cache/getLogStores', () => jest.mock('~/cache/getLogStores', () =>
jest.fn().mockReturnValue({ jest.fn().mockReturnValue({
@ -21,14 +20,11 @@ jest.mock('~/cache/getLogStores', () =>
); );
let mongoServer; let mongoServer;
let Role;
beforeAll(async () => { beforeAll(async () => {
mongoServer = await MongoMemoryServer.create(); mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri(); const mongoUri = mongoServer.getUri();
await db.connectDb(mongoUri); await mongoose.connect(mongoUri);
Role = db.models.Role;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,8 +1,7 @@
const { nanoid } = require('nanoid'); const { nanoid } = require('nanoid');
const { Constants } = require('librechat-data-provider'); const { Constants } = require('librechat-data-provider');
const db = require('~/lib/db/connectDb'); const { SharedLink, Conversation, logger } = require('@librechat/data-schemas');
const { getMessages } = require('./Message'); const { getMessages } = require('./Message');
const logger = require('~/config/winston');
class ShareServiceError extends Error { class ShareServiceError extends Error {
constructor(message, code) { constructor(message, code) {
@ -73,7 +72,7 @@ function anonymizeMessages(messages, newConvoId) {
async function getSharedMessages(shareId) { async function getSharedMessages(shareId) {
try { try {
const share = await db.models.SharedLink.findOne({ shareId, isPublic: true }) const share = await SharedLink.findOne({ shareId, isPublic: true })
.populate({ .populate({
path: 'messages', path: 'messages',
select: '-_id -__v -user', select: '-_id -__v -user',
@ -148,7 +147,7 @@ async function getSharedLinks(user, pageParam, pageSize, isPublic, sortBy, sortD
query.conversationId = { $in: query.conversationId }; query.conversationId = { $in: query.conversationId };
} }
const sharedLinks = await db.models.SharedLink.find(query) const sharedLinks = await SharedLink.find(query)
.sort(sort) .sort(sort)
.limit(pageSize + 1) .limit(pageSize + 1)
.select('-__v -user') .select('-__v -user')
@ -181,7 +180,7 @@ async function getSharedLinks(user, pageParam, pageSize, isPublic, sortBy, sortD
async function deleteAllSharedLinks(user) { async function deleteAllSharedLinks(user) {
try { try {
const result = await db.models.SharedLink.deleteMany({ user }); const result = await SharedLink.deleteMany({ user });
return { return {
message: 'All shared links deleted successfully', message: 'All shared links deleted successfully',
deletedCount: result.deletedCount, deletedCount: result.deletedCount,
@ -199,7 +198,6 @@ async function createSharedLink(user, conversationId) {
if (!user || !conversationId) { if (!user || !conversationId) {
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS'); throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
} }
const { SharedLink, Conversation } = db.models;
try { try {
const [existingShare, conversationMessages] = await Promise.all([ const [existingShare, conversationMessages] = await Promise.all([
SharedLink.findOne({ conversationId, isPublic: true }).select('-_id -__v -user').lean(), SharedLink.findOne({ conversationId, isPublic: true }).select('-_id -__v -user').lean(),
@ -241,7 +239,7 @@ async function getSharedLink(user, conversationId) {
} }
try { try {
const share = await db.models.SharedLink.findOne({ conversationId, user, isPublic: true }) const share = await SharedLink.findOne({ conversationId, user, isPublic: true })
.select('shareId -_id') .select('shareId -_id')
.lean(); .lean();
@ -265,7 +263,6 @@ async function updateSharedLink(user, shareId) {
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS'); throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
} }
const { SharedLink } = db.models;
try { try {
const share = await SharedLink.findOne({ shareId }).select('-_id -__v -user').lean(); const share = await SharedLink.findOne({ shareId }).select('-_id -__v -user').lean();
@ -316,7 +313,7 @@ async function deleteSharedLink(user, shareId) {
} }
try { try {
const result = await db.models.SharedLink.findOneAndDelete({ shareId, user }).lean(); const result = await SharedLink.findOneAndDelete({ shareId, user }).lean();
if (!result) { if (!result) {
return null; return null;

View file

@ -1,5 +1,5 @@
const { Token } = require('@librechat/data-schemas');
const { encryptV2 } = require('~/server/utils/crypto'); const { encryptV2 } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
/** /**
* Handles the OAuth token by creating or updating the token. * Handles the OAuth token by creating or updating the token.
@ -29,7 +29,6 @@ async function handleOAuthToken({
expiresIn: parseInt(expiresIn, 10) || 3600, expiresIn: parseInt(expiresIn, 10) || 3600,
}; };
const { Token } = db.models;
const existingToken = await Token.findToken({ userId, identifier }); const existingToken = await Token.findToken({ userId, identifier });
if (existingToken) { if (existingToken) {
return await Token.updateToken({ identifier }, tokenData); return await Token.updateToken({ identifier }, tokenData);

View file

@ -1,4 +1,4 @@
const db = require('~/lib/db/connectDb'); const { ToolCall } = require('@librechat/data-schemas');
/** /**
* Create a new tool call * Create a new tool call
* @param {IToolCallData} toolCallData - The tool call data * @param {IToolCallData} toolCallData - The tool call data
@ -6,7 +6,7 @@ const db = require('~/lib/db/connectDb');
*/ */
async function createToolCall(toolCallData) { async function createToolCall(toolCallData) {
try { try {
return await db.models.ToolCall.create(toolCallData); return await ToolCall.create(toolCallData);
} catch (error) { } catch (error) {
throw new Error(`Error creating tool call: ${error.message}`); throw new Error(`Error creating tool call: ${error.message}`);
} }
@ -19,7 +19,7 @@ async function createToolCall(toolCallData) {
*/ */
async function getToolCallById(id) { async function getToolCallById(id) {
try { try {
return await db.models.ToolCall.findById(id).lean(); return await ToolCall.findById(id).lean();
} catch (error) { } catch (error) {
throw new Error(`Error fetching tool call: ${error.message}`); throw new Error(`Error fetching tool call: ${error.message}`);
} }
@ -33,7 +33,7 @@ async function getToolCallById(id) {
*/ */
async function getToolCallsByMessage(messageId, userId) { async function getToolCallsByMessage(messageId, userId) {
try { try {
return await db.models.ToolCall.find({ messageId, user: userId }).lean(); return await ToolCall.find({ messageId, user: userId }).lean();
} catch (error) { } catch (error) {
throw new Error(`Error fetching tool calls: ${error.message}`); throw new Error(`Error fetching tool calls: ${error.message}`);
} }
@ -47,7 +47,7 @@ async function getToolCallsByMessage(messageId, userId) {
*/ */
async function getToolCallsByConvo(conversationId, userId) { async function getToolCallsByConvo(conversationId, userId) {
try { try {
return await db.models.ToolCall.find({ conversationId, user: userId }).lean(); return await ToolCall.find({ conversationId, user: userId }).lean();
} catch (error) { } catch (error) {
throw new Error(`Error fetching tool calls: ${error.message}`); throw new Error(`Error fetching tool calls: ${error.message}`);
} }
@ -61,7 +61,7 @@ async function getToolCallsByConvo(conversationId, userId) {
*/ */
async function updateToolCall(id, updateData) { async function updateToolCall(id, updateData) {
try { try {
return await db.models.ToolCall.findByIdAndUpdate(id, updateData, { new: true }).lean(); return await ToolCall.findByIdAndUpdate(id, updateData, { new: true }).lean();
} catch (error) { } catch (error) {
throw new Error(`Error updating tool call: ${error.message}`); throw new Error(`Error updating tool call: ${error.message}`);
} }
@ -79,7 +79,7 @@ async function deleteToolCalls(userId, conversationId) {
if (conversationId) { if (conversationId) {
query.conversationId = conversationId; query.conversationId = conversationId;
} }
return await db.models.ToolCall.deleteMany(query); return await ToolCall.deleteMany(query);
} catch (error) { } catch (error) {
throw new Error(`Error deleting tool call: ${error.message}`); throw new Error(`Error deleting tool call: ${error.message}`);
} }

View file

@ -1,9 +1,7 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { transactionSchema } = require('@librechat/data-schemas'); const { Balance, Transaction, logger } = require('@librechat/data-schemas');
const { getBalanceConfig } = require('~/server/services/Config'); const { getBalanceConfig } = require('~/server/services/Config');
const { getMultiplier, getCacheMultiplier } = require('./tx'); const { getMultiplier, getCacheMultiplier } = require('./tx');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const cancelRate = 1.15; const cancelRate = 1.15;
@ -23,7 +21,6 @@ const updateBalance = async ({ user, incrementValue, setValues }) => {
let maxRetries = 10; // Number of times to retry on conflict let maxRetries = 10; // Number of times to retry on conflict
let delay = 50; // Initial retry delay in ms let delay = 50; // Initial retry delay in ms
let lastError = null; let lastError = null;
const { Balance } = db.models;
for (let attempt = 1; attempt <= maxRetries; attempt++) { for (let attempt = 1; attempt <= maxRetries; attempt++) {
let currentBalanceDoc; let currentBalanceDoc;
@ -165,7 +162,6 @@ function calculateTokenValue(txn) {
* @returns {Promise<object>} - The created transaction. * @returns {Promise<object>} - The created transaction.
*/ */
async function createAutoRefillTransaction(txData) { async function createAutoRefillTransaction(txData) {
const Transaction = db.models.Transaction;
if (txData.rawAmount != null && isNaN(txData.rawAmount)) { if (txData.rawAmount != null && isNaN(txData.rawAmount)) {
return; return;
} }
@ -198,7 +194,7 @@ async function createTransaction(txData) {
return; return;
} }
const transaction = new db.models.Transaction(txData); const transaction = new Transaction(txData);
transaction.endpointTokenConfig = txData.endpointTokenConfig; transaction.endpointTokenConfig = txData.endpointTokenConfig;
calculateTokenValue(transaction); calculateTokenValue(transaction);
@ -228,7 +224,7 @@ async function createTransaction(txData) {
* @param {txData} txData - Transaction data. * @param {txData} txData - Transaction data.
*/ */
async function createStructuredTransaction(txData) { async function createStructuredTransaction(txData) {
const transaction = new db.models.Transaction({ const transaction = new Transaction({
...txData, ...txData,
endpointTokenConfig: txData.endpointTokenConfig, endpointTokenConfig: txData.endpointTokenConfig,
}); });
@ -329,7 +325,7 @@ function calculateStructuredTokenValue(txn) {
*/ */
async function getTransactions(filter) { async function getTransactions(filter) {
try { try {
return await db.models.Transaction.find(filter).lean(); return await Transaction.find(filter).lean();
} catch (error) { } catch (error) {
logger.error('Error querying transactions:', error); logger.error('Error querying transactions:', error);
throw error; throw error;

View file

@ -1,24 +1,19 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { Balance } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server'); const { MongoMemoryServer } = require('mongodb-memory-server');
const { spendTokens, spendStructuredTokens } = require('./spendTokens'); const { spendTokens, spendStructuredTokens } = require('./spendTokens');
const { getBalanceConfig } = require('~/server/services/Config'); const { getBalanceConfig } = require('~/server/services/Config');
const { getMultiplier, getCacheMultiplier } = require('./tx'); const { getMultiplier, getCacheMultiplier } = require('./tx');
const db = require('~/lib/db/connectDb');
const { createTransaction } = require('./Transaction'); const { createTransaction } = require('./Transaction');
// Mock the custom config module so we can control the balance flag. // Mock the custom config module so we can control the balance flag.
jest.mock('~/server/services/Config'); jest.mock('~/server/services/Config');
let mongoServer; let mongoServer;
let Balance;
let Transaction;
beforeAll(async () => { beforeAll(async () => {
mongoServer = await MongoMemoryServer.create(); mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri(); const mongoUri = mongoServer.getUri();
await db.connectDb(mongoUri); await mongoose.connect(mongoUri);
Balance = db.models.Balance;
Transaction = db.models.Transaction;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,9 +1,9 @@
const { Balance } = require('@librechat/data-schemas');
const { ViolationTypes } = require('librechat-data-provider'); const { ViolationTypes } = require('librechat-data-provider');
const { createAutoRefillTransaction } = require('./Transaction'); const { createAutoRefillTransaction } = require('./Transaction');
const { logViolation } = require('~/cache'); const { logViolation } = require('~/cache');
const { getMultiplier } = require('./tx'); const { getMultiplier } = require('./tx');
const { logger } = require('~/config'); const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
function isInvalidDate(date) { function isInvalidDate(date) {
return isNaN(date); return isNaN(date);
@ -26,7 +26,7 @@ const checkBalanceRecord = async function ({
const tokenCost = amount * multiplier; const tokenCost = amount * multiplier;
// Retrieve the balance record // Retrieve the balance record
let record = await db.models.Balance.findOne({ user }).lean(); let record = await Balance.findOne({ user }).lean();
if (!record) { if (!record) {
logger.debug('[Balance.check] No balance record found for user', { user }); logger.debug('[Balance.check] No balance record found for user', { user });
return { return {

View file

@ -1,7 +1,7 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { Message } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server'); const { MongoMemoryServer } = require('mongodb-memory-server');
const { getMessages, bulkSaveMessages } = require('./Message'); const { getMessages, bulkSaveMessages } = require('./Message');
const db = require('~/lib/db/connectDb');
// Original version of buildTree function // Original version of buildTree function
function buildTree({ messages, fileMap }) { function buildTree({ messages, fileMap }) {
@ -43,13 +43,10 @@ function buildTree({ messages, fileMap }) {
} }
let mongod; let mongod;
let Message;
beforeAll(async () => { beforeAll(async () => {
mongod = await MongoMemoryServer.create(); mongod = await MongoMemoryServer.create();
const uri = mongod.getUri(); const uri = mongod.getUri();
await db.connectDb(uri); await mongoose.connect(uri);
Message = db.models.Message;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,7 +1,6 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { Token, logger } = require('@librechat/data-schemas');
const { getRandomValues, hashToken } = require('~/server/utils/crypto'); const { getRandomValues, hashToken } = require('~/server/utils/crypto');
const logger = require('~/config/winston');
const db = require('~/lib/db/connectDb');
/** /**
* @module inviteUser * @module inviteUser
@ -23,7 +22,7 @@ const createInvite = async (email) => {
const fakeUserId = new mongoose.Types.ObjectId(); const fakeUserId = new mongoose.Types.ObjectId();
await db.models.Token.createToken({ await Token.createToken({
userId: fakeUserId, userId: fakeUserId,
email, email,
token: hash, token: hash,
@ -50,7 +49,7 @@ const getInvite = async (encodedToken, email) => {
try { try {
const token = decodeURIComponent(encodedToken); const token = decodeURIComponent(encodedToken);
const hash = await hashToken(token); const hash = await hashToken(token);
const invite = await db.models.Token.findToken({ token: hash, email }); const invite = await Token.findToken({ token: hash, email });
if (!invite) { if (!invite) {
throw new Error('Invite not found or email does not match'); throw new Error('Invite not found or email does not match');

View file

@ -1,7 +1,7 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server'); const { MongoMemoryServer } = require('mongodb-memory-server');
const { Transaction, Balance } = require('@librechat/data-schemas');
const { spendTokens, spendStructuredTokens } = require('./spendTokens'); const { spendTokens, spendStructuredTokens } = require('./spendTokens');
const db = require('~/lib/db/connectDb');
const { createTransaction, createAutoRefillTransaction } = require('./Transaction'); const { createTransaction, createAutoRefillTransaction } = require('./Transaction');
// Mock the logger to prevent console output during tests // Mock the logger to prevent console output during tests
@ -20,15 +20,9 @@ describe('spendTokens', () => {
let mongoServer; let mongoServer;
let userId; let userId;
let Transaction;
let Balance;
beforeAll(async () => { beforeAll(async () => {
mongoServer = await MongoMemoryServer.create(); mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri(); await mongoose.connect(mongoServer.getUri());
await db.connectDb(mongoUri);
Balance = db.models.Balance;
Transaction = db.models.Transaction;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,6 +1,7 @@
const openIdClient = require('openid-client');
const cookies = require('cookie'); const cookies = require('cookie');
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const openIdClient = require('openid-client');
const { User, Session, logger } = require('@librechat/data-schemas');
const { const {
registerUser, registerUser,
resetPassword, resetPassword,
@ -9,9 +10,7 @@ const {
setOpenIDAuthTokens, setOpenIDAuthTokens,
} = require('~/server/services/AuthService'); } = require('~/server/services/AuthService');
const { getOpenIdConfig } = require('~/strategies'); const { getOpenIdConfig } = require('~/strategies');
const { logger } = require('~/config');
const { isEnabled } = require('~/server/utils'); const { isEnabled } = require('~/server/utils');
const db = require('~/lib/db/connectDb');
const registrationController = async (req, res) => { const registrationController = async (req, res) => {
try { try {
@ -48,7 +47,7 @@ const resetPasswordController = async (req, res) => {
if (resetPasswordService instanceof Error) { if (resetPasswordService instanceof Error) {
return res.status(400).json(resetPasswordService); return res.status(400).json(resetPasswordService);
} else { } else {
await db.models.Session.deleteAllUserSessions({ userId: req.body.userId }); await Session.deleteAllUserSessions({ userId: req.body.userId });
return res.status(200).json(resetPasswordService); return res.status(200).json(resetPasswordService);
} }
} catch (e) { } catch (e) {
@ -70,7 +69,7 @@ const refreshController = async (req, res) => {
const openIdConfig = getOpenIdConfig(); const openIdConfig = getOpenIdConfig();
const tokenset = await openIdClient.refreshTokenGrant(openIdConfig, refreshToken); const tokenset = await openIdClient.refreshTokenGrant(openIdConfig, refreshToken);
const claims = tokenset.claims(); const claims = tokenset.claims();
const user = await findUser({ email: claims.email }); const user = await User.findUser({ email: claims.email });
if (!user) { if (!user) {
return res.status(401).redirect('/login'); return res.status(401).redirect('/login');
} }
@ -83,7 +82,7 @@ const refreshController = async (req, res) => {
} }
try { try {
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET); const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
const user = await db.models.User.getUserById(payload.id, '-password -__v -totpSecret'); const user = await User.getUserById(payload.id, '-password -__v -totpSecret');
if (!user) { if (!user) {
return res.status(401).redirect('/login'); return res.status(401).redirect('/login');
} }
@ -96,7 +95,7 @@ const refreshController = async (req, res) => {
} }
// Find the session with the hashed refresh token // Find the session with the hashed refresh token
const session = await db.models.Session.findSession({ const session = await Session.findSession({
userId: userId, userId: userId,
refreshToken: refreshToken, refreshToken: refreshToken,
}); });

View file

@ -1,6 +1,6 @@
const db = require('~/lib/db/connectDb'); const { Balance } = require('@librechat/data-schemas');
async function balanceController(req, res) { async function balanceController(req, res) {
const balanceData = await db.models.Balance.findOne( const balanceData = await Balance.findOne(
{ user: req.user.id }, { user: req.user.id },
'-_id tokenCredits autoRefillEnabled refillIntervalValue refillIntervalUnit lastRefill refillAmount', '-_id tokenCredits autoRefillEnabled refillIntervalValue refillIntervalUnit lastRefill refillAmount',
).lean(); ).lean();

View file

@ -1,3 +1,4 @@
const { User, logger } = require('@librechat/data-schemas');
const { const {
generateTOTPSecret, generateTOTPSecret,
generateBackupCodes, generateBackupCodes,
@ -5,9 +6,7 @@ const {
verifyBackupCode, verifyBackupCode,
getTOTPSecret, getTOTPSecret,
} = require('~/server/services/twoFactorService'); } = require('~/server/services/twoFactorService');
const { logger } = require('~/config');
const { encryptV3 } = require('~/server/utils/crypto'); const { encryptV3 } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
const safeAppTitle = (process.env.APP_TITLE || 'LibreChat').replace(/\s+/g, ''); const safeAppTitle = (process.env.APP_TITLE || 'LibreChat').replace(/\s+/g, '');
/** /**
@ -24,7 +23,7 @@ const enable2FA = async (req, res) => {
const encryptedSecret = encryptV3(secret); const encryptedSecret = encryptV3(secret);
// Update the user record: store the secret & backup codes and set twoFactorEnabled to false. // Update the user record: store the secret & backup codes and set twoFactorEnabled to false.
const user = await db.models.User.updateUser(userId, { const user = await User.updateUser(userId, {
totpSecret: encryptedSecret, totpSecret: encryptedSecret,
backupCodes: codeObjects, backupCodes: codeObjects,
twoFactorEnabled: false, twoFactorEnabled: false,
@ -46,7 +45,7 @@ const verify2FA = async (req, res) => {
try { try {
const userId = req.user.id; const userId = req.user.id;
const { token, backupCode } = req.body; const { token, backupCode } = req.body;
const user = await db.models.User.getUserById(userId); const user = await User.getUserById(userId);
if (!user || !user.totpSecret) { if (!user || !user.totpSecret) {
return res.status(400).json({ message: '2FA not initiated' }); return res.status(400).json({ message: '2FA not initiated' });
@ -78,7 +77,6 @@ const confirm2FA = async (req, res) => {
try { try {
const userId = req.user.id; const userId = req.user.id;
const { token } = req.body; const { token } = req.body;
const { User } = db.models;
const user = await User.getUserById(userId); const user = await User.getUserById(userId);
if (!user || !user.totpSecret) { if (!user || !user.totpSecret) {
@ -103,7 +101,7 @@ const confirm2FA = async (req, res) => {
const disable2FA = async (req, res) => { const disable2FA = async (req, res) => {
try { try {
const userId = req.user.id; const userId = req.user.id;
await db.models.User.updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false }); await User.updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false });
return res.status(200).json(); return res.status(200).json();
} catch (err) { } catch (err) {
logger.error('[disable2FA]', err); logger.error('[disable2FA]', err);
@ -118,7 +116,7 @@ const regenerateBackupCodes = async (req, res) => {
try { try {
const userId = req.user.id; const userId = req.user.id;
const { plainCodes, codeObjects } = await generateBackupCodes(); const { plainCodes, codeObjects } = await generateBackupCodes();
await db.models.User.updateUser(userId, { backupCodes: codeObjects }); await User.updateUser(userId, { backupCodes: codeObjects });
return res.status(200).json({ return res.status(200).json({
backupCodes: plainCodes, backupCodes: plainCodes,
backupCodesHash: codeObjects, backupCodesHash: codeObjects,

View file

@ -1,18 +1,11 @@
const { const {
Tools, Tools,
Constants,
FileSources, FileSources,
webSearchKeys, webSearchKeys,
extractWebSearchEnvVars, extractWebSearchEnvVars,
} = require('librechat-data-provider'); } = require('librechat-data-provider');
const { const { User, Session, Transaction, Balance, logger } = require('@librechat/data-schemas');
Balance, const { getFiles, deleteFiles, deleteConvos, deletePresets, deleteMessages } = require('~/models');
getFiles,
deleteFiles,
deleteConvos,
deletePresets,
deleteMessages,
} = require('~/models');
const { updateUserPluginAuth, deleteUserPluginAuth } = require('~/server/services/PluginService'); const { updateUserPluginAuth, deleteUserPluginAuth } = require('~/server/services/PluginService');
const { updateUserPluginsService, deleteUserKey } = require('~/server/services/UserService'); const { updateUserPluginsService, deleteUserKey } = require('~/server/services/UserService');
const { verifyEmail, resendVerificationEmail } = require('~/server/services/AuthService'); const { verifyEmail, resendVerificationEmail } = require('~/server/services/AuthService');
@ -20,9 +13,6 @@ const { needsRefresh, getNewS3URL } = require('~/server/services/Files/S3/crud')
const { processDeleteRequest } = require('~/server/services/Files/process'); const { processDeleteRequest } = require('~/server/services/Files/process');
const { deleteAllSharedLinks } = require('~/models/Share'); const { deleteAllSharedLinks } = require('~/models/Share');
const { deleteToolCalls } = require('~/models/ToolCall'); const { deleteToolCalls } = require('~/models/ToolCall');
const { Transaction } = require('~/models/Transaction');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const getUserController = async (req, res) => { const getUserController = async (req, res) => {
/** @type {MongoUser} */ /** @type {MongoUser} */
@ -36,7 +26,7 @@ const getUserController = async (req, res) => {
const originalAvatar = userData.avatar; const originalAvatar = userData.avatar;
try { try {
userData.avatar = await getNewS3URL(userData.avatar); userData.avatar = await getNewS3URL(userData.avatar);
await db.models.User.updateUser(userData.id, { avatar: userData.avatar }); await User.updateUser(userData.id, { avatar: userData.avatar });
} catch (error) { } catch (error) {
userData.avatar = originalAvatar; userData.avatar = originalAvatar;
logger.error('Error getting new S3 URL for avatar:', error); logger.error('Error getting new S3 URL for avatar:', error);
@ -47,7 +37,7 @@ const getUserController = async (req, res) => {
const getTermsStatusController = async (req, res) => { const getTermsStatusController = async (req, res) => {
try { try {
const user = await db.models.User.findById(req.user.id); const user = await User.findById(req.user.id);
if (!user) { if (!user) {
return res.status(404).json({ message: 'User not found' }); return res.status(404).json({ message: 'User not found' });
} }
@ -60,7 +50,7 @@ const getTermsStatusController = async (req, res) => {
const acceptTermsController = async (req, res) => { const acceptTermsController = async (req, res) => {
try { try {
const user = await db.models.User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true }); const user = await User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true });
if (!user) { if (!user) {
return res.status(404).json({ message: 'User not found' }); return res.status(404).json({ message: 'User not found' });
} }
@ -157,7 +147,7 @@ const deleteUserController = async (req, res) => {
try { try {
await deleteMessages({ user: user.id }); // delete user messages await deleteMessages({ user: user.id }); // delete user messages
await db.models.Session.deleteAllUserSessions({ userId: user.id }); // delete user sessions await Session.deleteAllUserSessions({ userId: user.id }); // delete user sessions
await Transaction.deleteMany({ user: user.id }); // delete user transactions await Transaction.deleteMany({ user: user.id }); // delete user transactions
await deleteUserKey({ userId: user.id, all: true }); // delete user keys await deleteUserKey({ userId: user.id, all: true }); // delete user keys
await Balance.deleteMany({ user: user._id }); // delete user balances await Balance.deleteMany({ user: user._id }); // delete user balances
@ -165,7 +155,7 @@ const deleteUserController = async (req, res) => {
/* TODO: Delete Assistant Threads */ /* TODO: Delete Assistant Threads */
await deleteConvos(user.id); // delete user convos await deleteConvos(user.id); // delete user convos
await deleteUserPluginAuth(user.id, null, true); // delete user plugin auth await deleteUserPluginAuth(user.id, null, true); // delete user plugin auth
await db.models.User.deleteUserById(user.id); // delete user await User.deleteUserById(user.id); // delete user
await deleteAllSharedLinks(user.id); // delete user shared links await deleteAllSharedLinks(user.id); // delete user shared links
await deleteUserFiles(req); // delete user files await deleteUserFiles(req); // delete user files
await deleteFiles(null, user.id); // delete database files in case of orphaned files from previous steps await deleteFiles(null, user.id); // delete database files in case of orphaned files from previous steps

View file

@ -5,8 +5,7 @@ const {
getTOTPSecret, getTOTPSecret,
} = require('~/server/services/twoFactorService'); } = require('~/server/services/twoFactorService');
const { setAuthTokens } = require('~/server/services/AuthService'); const { setAuthTokens } = require('~/server/services/AuthService');
const { logger } = require('~/config'); const { User, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
/** /**
* Verifies the 2FA code during login using a temporary token. * Verifies the 2FA code during login using a temporary token.
@ -25,7 +24,7 @@ const verify2FAWithTempToken = async (req, res) => {
return res.status(401).json({ message: 'Invalid or expired temporary token' }); return res.status(401).json({ message: 'Invalid or expired temporary token' });
} }
const user = await db.models.User.getUserById(payload.userId); const user = await User.getUserById(payload.userId);
if (!user || !user.twoFactorEnabled) { if (!user || !user.twoFactorEnabled) {
return res.status(400).json({ message: '2FA is not enabled for this user' }); return res.status(400).json({ message: '2FA is not enabled for this user' });
} }

View file

@ -5,9 +5,7 @@ const { isEnabled, removePorts } = require('~/server/utils');
const keyvMongo = require('~/cache/keyvMongo'); const keyvMongo = require('~/cache/keyvMongo');
const denyRequest = require('./denyRequest'); const denyRequest = require('./denyRequest');
const { getLogStores } = require('~/cache'); const { getLogStores } = require('~/cache');
const { logger } = require('~/config'); const { User, logger } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
const banCache = new Keyv({ store: keyvMongo, namespace: ViolationTypes.BAN, ttl: 0 }); const banCache = new Keyv({ store: keyvMongo, namespace: ViolationTypes.BAN, ttl: 0 });
const message = 'Your account has been temporarily banned due to violations of our service.'; const message = 'Your account has been temporarily banned due to violations of our service.';
@ -58,7 +56,7 @@ const checkBan = async (req, res, next = () => {}) => {
let userId = req.user?.id ?? req.user?._id ?? null; let userId = req.user?.id ?? req.user?._id ?? null;
if (!userId && req?.body?.email) { if (!userId && req?.body?.email) {
const user = await db.models.User.findUser({ email: req.body.email }, '_id'); const user = await User.findUser({ email: req.body.email }, '_id');
userId = user?._id ? user._id.toString() : userId; userId = user?._id ? user._id.toString() : userId;
} }

View file

@ -1,5 +1,5 @@
const { deleteTokens } = require('@librechat/data-schemas');
const { getInvite } = require('~/models/inviteUser'); const { getInvite } = require('~/models/inviteUser');
const db = require('~/lib/db/connectDb');
async function checkInviteUser(req, res, next) { async function checkInviteUser(req, res, next) {
const token = req.body.token; const token = req.body.token;
@ -16,7 +16,7 @@ async function checkInviteUser(req, res, next) {
return res.status(400).json({ message: 'Invalid invite token' }); return res.status(400).json({ message: 'Invalid invite token' });
} }
await db.models.Token.deleteTokens({ token: invite.token }); await deleteTokens({ token: invite.token });
req.invite = invite; req.invite = invite;
next(); next();
} catch (error) { } catch (error) {

View file

@ -1,6 +1,5 @@
const { Balance, logger } = require('@librechat/data-schemas');
const { getBalanceConfig } = require('~/server/services/Config'); const { getBalanceConfig } = require('~/server/services/Config');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/** /**
* Middleware to synchronize user balance settings with current balance configuration. * Middleware to synchronize user balance settings with current balance configuration.
@ -20,14 +19,14 @@ const setBalanceConfig = async (req, res, next) => {
} }
const userId = req.user._id; const userId = req.user._id;
const userBalanceRecord = await db.models.Balance.findOne({ user: userId }).lean(); const userBalanceRecord = await Balance.findOne({ user: userId }).lean();
const updateFields = buildUpdateFields(balanceConfig, userBalanceRecord); const updateFields = buildUpdateFields(balanceConfig, userBalanceRecord);
if (Object.keys(updateFields).length === 0) { if (Object.keys(updateFields).length === 0) {
return next(); return next();
} }
await db.models.Balance.findOneAndUpdate( await Balance.findOneAndUpdate(
{ user: userId }, { user: userId },
{ $set: updateFields }, { $set: updateFields },
{ upsert: true, new: true }, { upsert: true, new: true },

View file

@ -1,5 +1,6 @@
const express = require('express'); const express = require('express');
const { ContentTypes } = require('librechat-data-provider'); const { ContentTypes } = require('librechat-data-provider');
const { Message, logger } = require('@librechat/data-schemas');
const { const {
saveConvo, saveConvo,
saveMessage, saveMessage,
@ -13,8 +14,6 @@ const { requireJwtAuth, validateMessageReq } = require('~/server/middleware');
const { cleanUpPrimaryKeyValue } = require('~/lib/utils/misc'); const { cleanUpPrimaryKeyValue } = require('~/lib/utils/misc');
const { getConvosQueried } = require('~/models/Conversation'); const { getConvosQueried } = require('~/models/Conversation');
const { countTokens } = require('~/server/utils'); const { countTokens } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const router = express.Router(); const router = express.Router();
router.use(requireJwtAuth); router.use(requireJwtAuth);
@ -40,7 +39,7 @@ router.get('/', async (req, res) => {
const sortOrder = sortDirection === 'asc' ? 1 : -1; const sortOrder = sortDirection === 'asc' ? 1 : -1;
if (conversationId && messageId) { if (conversationId && messageId) {
const message = await db.models.Message.findOne({ const message = await Message.findOne({
conversationId, conversationId,
messageId, messageId,
user: user, user: user,
@ -51,14 +50,14 @@ router.get('/', async (req, res) => {
if (cursor) { if (cursor) {
filter[sortField] = sortOrder === 1 ? { $gt: cursor } : { $lt: cursor }; filter[sortField] = sortOrder === 1 ? { $gt: cursor } : { $lt: cursor };
} }
const messages = await db.models.Message.find(filter) const messages = await Message.find(filter)
.sort({ [sortField]: sortOrder }) .sort({ [sortField]: sortOrder })
.limit(pageSize + 1) .limit(pageSize + 1)
.lean(); .lean();
const nextCursor = messages.length > pageSize ? messages.pop()[sortField] : null; const nextCursor = messages.length > pageSize ? messages.pop()[sortField] : null;
response = { messages, nextCursor }; response = { messages, nextCursor };
} else if (search) { } else if (search) {
const searchResults = await db.models.Message.meiliSearch(search, undefined, true); const searchResults = await Message.meiliSearch(search, undefined, true);
const messages = searchResults.hits || []; const messages = searchResults.hits || [];

View file

@ -1,6 +1,7 @@
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const { nanoid } = require('nanoid'); const { nanoid } = require('nanoid');
const { tool } = require('@langchain/core/tools'); const { tool } = require('@langchain/core/tools');
const { findToken } = require('@librechat/data-schemas');
const { GraphEvents, sleep } = require('@librechat/agents'); const { GraphEvents, sleep } = require('@librechat/agents');
const { const {
Time, Time,
@ -231,10 +232,9 @@ async function createActionTool({
}; };
const tokenPromises = []; const tokenPromises = [];
const { Token } = db.models; tokenPromises.push(findToken({ userId, type: 'oauth', identifier }));
tokenPromises.push(Token.findToken({ userId, type: 'oauth', identifier }));
tokenPromises.push( tokenPromises.push(
Token.findToken({ findToken({
userId, userId,
type: 'oauth_refresh', type: 'oauth_refresh',
identifier: `${identifier}:refresh`, identifier: `${identifier}:refresh`,

View file

@ -1,11 +1,11 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const sharp = require('sharp'); const sharp = require('sharp');
const { updateUser, logger } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize'); const { resizeImageBuffer } = require('../images/resize');
const { updateFile } = require('~/models/File'); const { updateFile } = require('~/models/File');
const { logger } = require('~/config');
const { saveBufferToAzure } = require('./crud'); const { saveBufferToAzure } = require('./crud');
const db = require('~/lib/db/connectDb');
/** /**
* Uploads an image file to Azure Blob Storage. * Uploads an image file to Azure Blob Storage.
* It resizes and converts the image similar to your Firebase implementation. * It resizes and converts the image similar to your Firebase implementation.
@ -107,7 +107,7 @@ async function processAzureAvatar({ buffer, userId, manual, basePath = 'images',
const isManual = manual === 'true'; const isManual = manual === 'true';
const url = `${downloadURL}?manual=${isManual}`; const url = `${downloadURL}?manual=${isManual}`;
if (isManual) { if (isManual) {
await db.models?.User.updateUser(userId, { avatar: url }); await updateUser(userId, { avatar: url });
} }
return url; return url;
} catch (error) { } catch (error) {

View file

@ -4,8 +4,7 @@ const sharp = require('sharp');
const { resizeImageBuffer } = require('../images/resize'); const { resizeImageBuffer } = require('../images/resize');
const { saveBufferToFirebase } = require('./crud'); const { saveBufferToFirebase } = require('./crud');
const { updateFile } = require('~/models/File'); const { updateFile } = require('~/models/File');
const { logger } = require('~/config'); const { logger, updateUser } = require('@librechat/data-schemas');
const db = require('~/lib/db/connectDb');
/** /**
* Converts an image file to the target format. The function first resizes the image based on the specified * Converts an image file to the target format. The function first resizes the image based on the specified
@ -99,7 +98,7 @@ async function processFirebaseAvatar({ buffer, userId, manual }) {
const url = `${downloadURL}?manual=${isManual}`; const url = `${downloadURL}?manual=${isManual}`;
if (isManual) { if (isManual) {
await db.models.User.updateUser(userId, { avatar: url }); await updateUser(userId, { avatar: url });
} }
return url; return url;

View file

@ -1,9 +1,9 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const sharp = require('sharp'); const sharp = require('sharp');
const { updateUser } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize'); const { resizeImageBuffer } = require('../images/resize');
const { updateFile } = require('~/models/File'); const { updateFile } = require('~/models/File');
const db = require('~/lib/db/connectDb');
/** /**
* Converts an image file to the target format. The function first resizes the image based on the specified * Converts an image file to the target format. The function first resizes the image based on the specified
@ -141,7 +141,7 @@ async function processLocalAvatar({ buffer, userId, manual }) {
let url = `${urlRoute}?manual=${isManual}`; let url = `${urlRoute}?manual=${isManual}`;
if (isManual) { if (isManual) {
await db.models?.User.updateUser(userId, { avatar: url }); await updateUser(userId, { avatar: url });
} }
return url; return url;

View file

@ -1,11 +1,10 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const sharp = require('sharp'); const sharp = require('sharp');
const { logger, updateUser } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize'); const { resizeImageBuffer } = require('../images/resize');
const { saveBufferToS3 } = require('./crud');
const { updateFile } = require('~/models/File'); const { updateFile } = require('~/models/File');
const { logger } = require('~/config'); const { saveBufferToS3 } = require('./crud');
const db = require('~/lib/db/connectDb');
const defaultBasePath = 'images'; const defaultBasePath = 'images';
@ -102,7 +101,7 @@ async function processS3Avatar({ buffer, userId, manual, basePath = defaultBaseP
try { try {
const downloadURL = await saveBufferToS3({ userId, buffer, fileName: 'avatar.png', basePath }); const downloadURL = await saveBufferToS3({ userId, buffer, fileName: 'avatar.png', basePath });
if (manual === 'true') { if (manual === 'true') {
await db.models?.User.updateUser(userId, { avatar: downloadURL }); await updateUser(userId, { avatar: downloadURL });
} }
return downloadURL; return downloadURL;
} catch (error) { } catch (error) {

View file

@ -1,7 +1,7 @@
const { ErrorTypes } = require('librechat-data-provider'); const { ErrorTypes } = require('librechat-data-provider');
const { encrypt, decrypt } = require('~/server/utils'); const { Key, logger, updateUser } = require('@librechat/data-schemas');
const { logger } = require('~/config'); const { encrypt, decrypt } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
/** /**
* Updates the plugins for a user based on the action specified (install/uninstall). * Updates the plugins for a user based on the action specified (install/uninstall).
* @async * @async
@ -16,11 +16,10 @@ const db = require('~/lib/db/connectDb');
const updateUserPluginsService = async (user, pluginKey, action) => { const updateUserPluginsService = async (user, pluginKey, action) => {
try { try {
const userPlugins = user.plugins || []; const userPlugins = user.plugins || [];
const { User } = db.models;
if (action === 'install') { if (action === 'install') {
return await User.updateUser(user._id, { plugins: [...userPlugins, pluginKey] }); return await updateUser(user._id, { plugins: [...userPlugins, pluginKey] });
} else if (action === 'uninstall') { } else if (action === 'uninstall') {
return await User.updateUser(user._id, { return await updateUser(user._id, {
plugins: userPlugins.filter((plugin) => plugin !== pluginKey), plugins: userPlugins.filter((plugin) => plugin !== pluginKey),
}); });
} }
@ -42,7 +41,7 @@ const updateUserPluginsService = async (user, pluginKey, action) => {
* an error indicating that there is no user key available. * an error indicating that there is no user key available.
*/ */
const getUserKey = async ({ userId, name }) => { const getUserKey = async ({ userId, name }) => {
const keyValue = await db.models.Key.findOne({ userId, name }).lean(); const keyValue = await Key.findOne({ userId, name }).lean();
if (!keyValue) { if (!keyValue) {
throw new Error( throw new Error(
JSON.stringify({ JSON.stringify({
@ -89,7 +88,7 @@ const getUserKeyValues = async ({ userId, name }) => {
* returns its expiry date. If the key is not found, it returns null for the expiry date. * returns its expiry date. If the key is not found, it returns null for the expiry date.
*/ */
const getUserKeyExpiry = async ({ userId, name }) => { const getUserKeyExpiry = async ({ userId, name }) => {
const keyValue = await db.models.Key.findOne({ userId, name }).lean(); const keyValue = await Key.findOne({ userId, name }).lean();
if (!keyValue) { if (!keyValue) {
return { expiresAt: null }; return { expiresAt: null };
} }
@ -123,7 +122,7 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
// make sure to remove if already present // make sure to remove if already present
updateQuery.$unset = { expiresAt }; updateQuery.$unset = { expiresAt };
} }
return await db.models.Key.findOneAndUpdate({ userId, name }, updateQuery, { return await Key.findOneAndUpdate({ userId, name }, updateQuery, {
upsert: true, upsert: true,
new: true, new: true,
}).lean(); }).lean();
@ -143,10 +142,10 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
*/ */
const deleteUserKey = async ({ userId, name, all = false }) => { const deleteUserKey = async ({ userId, name, all = false }) => {
if (all) { if (all) {
return await db.models.Key.deleteMany({ userId }); return await Key.deleteMany({ userId });
} }
await db.models.Key.findOneAndDelete({ userId, name }).lean(); await Key.findOneAndDelete({ userId, name }).lean();
}; };
/** /**

View file

@ -1,7 +1,6 @@
const { webcrypto } = require('node:crypto'); const { webcrypto } = require('node:crypto');
const { decryptV3, decryptV2 } = require('../utils/crypto'); const { User } = require('@librechat/data-schemas');
const { hashBackupCode } = require('~/server/utils/crypto'); const { hashBackupCode, decryptV3, decryptV2 } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
// Base32 alphabet for TOTP secret encoding. // Base32 alphabet for TOTP secret encoding.
const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
@ -173,7 +172,7 @@ const verifyBackupCode = async ({ user, backupCode }) => {
: codeObj, : codeObj,
); );
// Update the user record with the marked backup code. // Update the user record with the marked backup code.
await db.models.User.updateUser(user._id, { backupCodes: updatedBackupCodes }); await User.updateUser(user._id, { backupCodes: updatedBackupCodes });
return true; return true;
} }
return false; return false;

View file

@ -3,10 +3,9 @@ const { MongoMemoryServer } = require('mongodb-memory-server');
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const { Strategy: AppleStrategy } = require('passport-apple'); const { Strategy: AppleStrategy } = require('passport-apple');
const socialLogin = require('./socialLogin'); const socialLogin = require('./socialLogin');
const { logger } = require('~/config');
const { createSocialUser, handleExistingUser } = require('./process'); const { createSocialUser, handleExistingUser } = require('./process');
const { isEnabled } = require('~/server/utils'); const { isEnabled } = require('~/server/utils');
const db = require('~/lib/db/connectDb'); const { User, logger } = require('@librechat/data-schemas');
// Mocking external dependencies // Mocking external dependencies
jest.mock('jsonwebtoken'); jest.mock('jsonwebtoken');
@ -29,14 +28,11 @@ describe('Apple Login Strategy', () => {
let appleStrategyInstance; let appleStrategyInstance;
const OLD_ENV = process.env; const OLD_ENV = process.env;
let getProfileDetails; let getProfileDetails;
let User;
// Start and stop in-memory MongoDB // Start and stop in-memory MongoDB
beforeAll(async () => { beforeAll(async () => {
mongoServer = await MongoMemoryServer.create(); mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri(); const mongoUri = mongoServer.getUri();
await db.connectDb(mongoUri); await mongoose.connect(mongoUri);
User = db.models.User;
}); });
afterAll(async () => { afterAll(async () => {

View file

@ -1,7 +1,6 @@
const { SystemRoles } = require('librechat-data-provider'); const { SystemRoles } = require('librechat-data-provider');
const { User, logger } = require('@librechat/data-schemas');
const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt'); const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
// JWT strategy // JWT strategy
const jwtLogin = () => const jwtLogin = () =>
@ -12,7 +11,6 @@ const jwtLogin = () =>
}, },
async (payload, done) => { async (payload, done) => {
try { try {
const {User} = db.models;
const user = await User.getUserById(payload?.id, '-password -__v -totpSecret'); const user = await User.getUserById(payload?.id, '-password -__v -totpSecret');
if (user) { if (user) {
user.id = user._id.toString(); user.id = user._id.toString();

View file

@ -1,10 +1,10 @@
const fs = require('fs'); const fs = require('fs');
const LdapStrategy = require('passport-ldapauth'); const LdapStrategy = require('passport-ldapauth');
const { SystemRoles } = require('librechat-data-provider'); const { SystemRoles } = require('librechat-data-provider');
const { User, createUser, findUser, updateUser } = require('@librechat/data-schemas');
const { getBalanceConfig } = require('~/server/services/Config');
const { isEnabled } = require('~/server/utils'); const { isEnabled } = require('~/server/utils');
const logger = require('~/utils/logger'); const logger = require('~/utils/logger');
const db = require('~/lib/db/connectDb');
const { getBalanceConfig } = require('~/server/services/Config');
const { const {
LDAP_URL, LDAP_URL,
@ -81,7 +81,6 @@ const ldapOptions = {
}; };
const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => { const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => {
const { User } = db.models;
if (!userinfo) { if (!userinfo) {
return done(null, false, { message: 'Invalid credentials' }); return done(null, false, { message: 'Invalid credentials' });
} }
@ -90,7 +89,7 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => {
const ldapId = const ldapId =
(LDAP_ID && userinfo[LDAP_ID]) || userinfo.uid || userinfo.sAMAccountName || userinfo.mail; (LDAP_ID && userinfo[LDAP_ID]) || userinfo.uid || userinfo.sAMAccountName || userinfo.mail;
let user = await User.findUser({ ldapId }); let user = await findUser({ ldapId });
const fullNameAttributes = LDAP_FULL_NAME && LDAP_FULL_NAME.split(','); const fullNameAttributes = LDAP_FULL_NAME && LDAP_FULL_NAME.split(',');
const fullName = const fullName =
@ -126,8 +125,7 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => {
role: isFirstRegisteredUser ? SystemRoles.ADMIN : SystemRoles.USER, role: isFirstRegisteredUser ? SystemRoles.ADMIN : SystemRoles.USER,
}; };
const balanceConfig = await getBalanceConfig(); const balanceConfig = await getBalanceConfig();
const userId = await createUser(user, balanceConfig);
const userId = await User.createUser(user, balanceConfig);
user._id = userId; user._id = userId;
} else { } else {
// Users registered in LDAP are assumed to have their user information managed in LDAP, // Users registered in LDAP are assumed to have their user information managed in LDAP,
@ -139,7 +137,7 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => {
user.name = fullName; user.name = fullName;
} }
user = await User.updateUser(user._id, user); user = await updateUser(user._id, user);
done(null, user); done(null, user);
} catch (err) { } catch (err) {
logger.error('[ldapStrategy]', err); logger.error('[ldapStrategy]', err);

View file

@ -1,10 +1,9 @@
const { User, logger } = require('@librechat/data-schemas');
const { errorsToString } = require('librechat-data-provider'); const { errorsToString } = require('librechat-data-provider');
const { Strategy: PassportLocalStrategy } = require('passport-local'); const { Strategy: PassportLocalStrategy } = require('passport-local');
const { comparePassword } = require('~/models');
const { isEnabled, checkEmailConfig } = require('~/server/utils'); const { isEnabled, checkEmailConfig } = require('~/server/utils');
const { comparePassword } = require('~/models');
const { loginSchema } = require('./validators'); const { loginSchema } = require('./validators');
const logger = require('~/utils/logger');
const db = require('~/lib/db/connectDb');
// Unix timestamp for 2024-06-07 15:20:18 Eastern Time // Unix timestamp for 2024-06-07 15:20:18 Eastern Time
const verificationEnabledTimestamp = 1717788018; const verificationEnabledTimestamp = 1717788018;
@ -15,7 +14,6 @@ async function validateLoginRequest(req) {
} }
async function passportLogin(req, email, password, done) { async function passportLogin(req, email, password, done) {
const {User} = db.models;
try { try {
const validationError = await validateLoginRequest(req); const validationError = await validateLoginRequest(req);
if (validationError) { if (validationError) {

View file

@ -1,14 +1,14 @@
const { CacheKeys } = require('librechat-data-provider');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const passport = require('passport'); const passport = require('passport');
const jwtDecode = require('jsonwebtoken/decode');
const { HttpsProxyAgent } = require('https-proxy-agent');
const client = require('openid-client'); const client = require('openid-client');
const jwtDecode = require('jsonwebtoken/decode');
const { CacheKeys } = require('librechat-data-provider');
const { HttpsProxyAgent } = require('https-proxy-agent');
const { User, logger } = require('@librechat/data-schemas');
const { Strategy: OpenIDStrategy } = require('openid-client/passport'); const { Strategy: OpenIDStrategy } = require('openid-client/passport');
const { getStrategyFunctions } = require('~/server/services/Files/strategies'); const { getStrategyFunctions } = require('~/server/services/Files/strategies');
const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');
const getLogStores = require('~/cache/getLogStores'); const getLogStores = require('~/cache/getLogStores');
const { isEnabled } = require('~/server/utils');
/** /**
* @typedef {import('openid-client').ClientMetadata} ClientMetadata * @typedef {import('openid-client').ClientMetadata} ClientMetadata
@ -212,7 +212,6 @@ function convertToUsername(input, defaultValue = '') {
* @throws {Error} If an error occurs during the setup process. * @throws {Error} If an error occurs during the setup process.
*/ */
async function setupOpenId() { async function setupOpenId() {
const { User } = db.models;
try { try {
/** @type {ClientMetadata} */ /** @type {ClientMetadata} */
const clientMetadata = { const clientMetadata = {

View file

@ -9,18 +9,6 @@ const mockFindUser = jest.fn();
const mockUpdateUser = jest.fn(); const mockUpdateUser = jest.fn();
let User; let User;
jest.mock('@librechat/data-schemas', () => {
return {
registerModels: jest.fn().mockReturnValue({
User: {
createUser: mockCreateUser,
findUser: mockFindUser,
updateUser: mockUpdateUser,
},
}),
};
});
const mockModels = { const mockModels = {
User: { User: {
createUser: mockCreateUser, createUser: mockCreateUser,

View file

@ -1,7 +1,7 @@
const { FileSources } = require('librechat-data-provider'); const { FileSources } = require('librechat-data-provider');
const { updateUser, createUser, getUserById } = require('@librechat/data-schemas');
const { getStrategyFunctions } = require('~/server/services/Files/strategies'); const { getStrategyFunctions } = require('~/server/services/Files/strategies');
const { resizeAvatar } = require('~/server/services/Files/images/avatar'); const { resizeAvatar } = require('~/server/services/Files/images/avatar');
const db = require('~/lib/db/connectDb');
const { getBalanceConfig } = require('~/server/services/Config'); const { getBalanceConfig } = require('~/server/services/Config');
/** /**
@ -35,7 +35,7 @@ const handleExistingUser = async (oldUser, avatarUrl) => {
} }
if (updatedAvatar) { if (updatedAvatar) {
await db.models.User.updateUser(oldUser._id, { avatar: updatedAvatar }); await updateUser(oldUser._id, { avatar: updatedAvatar });
} }
}; };
@ -80,7 +80,7 @@ const createSocialUser = async ({
}; };
const balanceConfig = await getBalanceConfig(); const balanceConfig = await getBalanceConfig();
const newUserId = await db.models.User.createUser(update, balanceConfig); const newUserId = await createUser(update, balanceConfig);
const fileStrategy = process.env.CDN_PROVIDER; const fileStrategy = process.env.CDN_PROVIDER;
const isLocal = fileStrategy === FileSources.local; const isLocal = fileStrategy === FileSources.local;
@ -91,10 +91,10 @@ const createSocialUser = async ({
}); });
const { processAvatar } = getStrategyFunctions(fileStrategy); const { processAvatar } = getStrategyFunctions(fileStrategy);
const avatar = await processAvatar({ buffer: resizedBuffer, userId: newUserId }); const avatar = await processAvatar({ buffer: resizedBuffer, userId: newUserId });
await User.updateUser(newUserId, { avatar }); await updateUser(newUserId, { avatar });
} }
return await User.getUserById(newUserId); return await getUserById(newUserId);
}; };
module.exports = { module.exports = {

View file

@ -1,7 +1,6 @@
const { findUser, logger } = require('@librechat/data-schemas');
const { createSocialUser, handleExistingUser } = require('./process'); const { createSocialUser, handleExistingUser } = require('./process');
const { isEnabled } = require('~/server/utils'); const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const socialLogin = const socialLogin =
(provider, getProfileDetails) => async (accessToken, refreshToken, idToken, profile, cb) => { (provider, getProfileDetails) => async (accessToken, refreshToken, idToken, profile, cb) => {
@ -11,7 +10,7 @@ const socialLogin =
profile, profile,
}); });
const oldUser = await db.models.User.findUser({ email: email.trim() }); const oldUser = await findUser({ email: email.trim() });
const ALLOW_SOCIAL_REGISTRATION = isEnabled(process.env.ALLOW_SOCIAL_REGISTRATION); const ALLOW_SOCIAL_REGISTRATION = isEnabled(process.env.ALLOW_SOCIAL_REGISTRATION);
if (oldUser) { if (oldUser) {

View file

@ -1,9 +1,9 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const { isEnabled } = require('~/server/utils/handleText'); const { isEnabled } = require('~/server/utils/handleText');
const { createTransaction } = require('~/models/Transaction'); const { createTransaction } = require('~/models/Transaction');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -65,7 +65,7 @@ const connect = require('./connect');
} }
// Validate the user // Validate the user
const user = await db.models.User.findOne({ email }).lean(); const user = await User.findOne({ email }).lean();
if (!user) { if (!user) {
console.red('Error: No user with that email was found!'); console.red('Error: No user with that email was found!');
silentExit(1); silentExit(1);

View file

@ -1,8 +1,8 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const banViolation = require('~/cache/banViolation'); const banViolation = require('~/cache/banViolation');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -44,7 +44,7 @@ const connect = require('./connect');
silentExit(1); silentExit(1);
} }
const user = await db.models.User.findOne({ email }).lean(); const user = await User.findOne({ email }).lean();
if (!user) { if (!user) {
console.red('Error: No user with that email was found!'); console.red('Error: No user with that email was found!');
silentExit(1); silentExit(1);

View file

@ -1,8 +1,8 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { registerUser } = require('~/server/services/AuthService'); const { registerUser } = require('~/server/services/AuthService');
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -92,7 +92,7 @@ or the user will need to attempt logging in to have a verification link sent to
} }
} }
const userExists = await db.models.User.findOne({ $or: [{ email }, { username }] }); const userExists = await User.findOne({ $or: [{ email }, { username }] });
if (userExists) { if (userExists) {
console.red('Error: A user with that email or username already exists!'); console.red('Error: A user with that email or username already exists!');
silentExit(1); silentExit(1);

View file

@ -1,7 +1,7 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -20,10 +20,10 @@ const connect = require('./connect');
} else { } else {
email = await askQuestion('Email:'); email = await askQuestion('Email:');
} }
let user = await db.models.User.findOne({ email: email }); let user = await User.findOne({ email: email });
if (user !== null) { if (user !== null) {
if ((await askQuestion(`Delete user ${user}?`)) === 'y') { if ((await askQuestion(`Delete user ${user}?`)) === 'y') {
user = await db.models.User.findOneAndDelete({ _id: user._id }); user = await User.findOneAndDelete({ _id: user._id });
if (user !== null) { if (user !== null) {
console.yellow(`Deleted user ${user}`); console.yellow(`Deleted user ${user}`);
} else { } else {

View file

@ -1,9 +1,9 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { sendEmail, checkEmailConfig } = require('~/server/utils'); const { sendEmail, checkEmailConfig } = require('~/server/utils');
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const { createInvite } = require('~/models/inviteUser'); const { createInvite } = require('~/models/inviteUser');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -40,7 +40,7 @@ const connect = require('./connect');
} }
// Check if the user already exists // Check if the user already exists
const userExists = await db.models.User.findOne({ email }); const userExists = await User.findOne({ email });
if (userExists) { if (userExists) {
console.red('Error: A user with that email already exists!'); console.red('Error: A user with that email already exists!');
silentExit(1); silentExit(1);

View file

@ -1,8 +1,7 @@
const path = require('path'); const path = require('path');
const { User, Balance } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { silentExit } = require('./helpers'); const { silentExit } = require('./helpers');
const Balance = require('~/models/Balance');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -15,7 +14,7 @@ const connect = require('./connect');
console.purple('Show the balance of all users'); console.purple('Show the balance of all users');
console.purple('-----------------------------'); console.purple('-----------------------------');
let users = await db.models.User.find({}); let users = await User.find({});
for (const user of users) { for (const user of users) {
let balance = await Balance.findOne({ user: user._id }); let balance = await Balance.findOne({ user: user._id });
if (balance !== null) { if (balance !== null) {

View file

@ -1,12 +1,12 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const connect = require('./connect'); const connect = require('./connect');
const db = require('~/lib/db/connectDb');
const listUsers = async () => { const listUsers = async () => {
try { try {
await connect(); await connect();
const users = await db.models.User.find({}, 'email provider avatar username name createdAt'); const users = await User.find({}, 'email provider avatar username name createdAt');
console.log('\nUser List:'); console.log('\nUser List:');
console.log('----------------------------------------'); console.log('----------------------------------------');

View file

@ -1,8 +1,8 @@
const path = require('path'); const path = require('path');
const { User } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const db = require('~/lib/db/connectDb');
const connect = require('./connect');
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const connect = require('./connect');
(async () => { (async () => {
await connect(); await connect();
@ -20,7 +20,7 @@ const { askQuestion, silentExit } = require('./helpers');
} }
try { try {
const result = await db.models.User.updateMany({}, { $set: { termsAccepted: false } }); const result = await User.updateMany({}, { $set: { termsAccepted: false } });
console.green(`Updated ${result.modifiedCount} user(s).`); console.green(`Updated ${result.modifiedCount} user(s).`);
} catch (error) { } catch (error) {
console.red('Error resetting terms acceptance:', error); console.red('Error resetting terms acceptance:', error);

View file

@ -1,8 +1,8 @@
const path = require('path'); const path = require('path');
const { User, Balance } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers'); const { askQuestion, silentExit } = require('./helpers');
const { isEnabled } = require('~/server/utils/handleText'); const { isEnabled } = require('~/server/utils/handleText');
const db = require('~/lib/db/connectDb');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -56,7 +56,7 @@ const connect = require('./connect');
} }
// Validate the user // Validate the user
const user = await db.models.User.findOne({ email }).lean(); const user = await User.findOne({ email }).lean();
if (!user) { if (!user) {
console.red('Error: No user with that email was found!'); console.red('Error: No user with that email was found!');
silentExit(1); silentExit(1);
@ -64,7 +64,7 @@ const connect = require('./connect');
console.purple(`Found user: ${user.email}`); console.purple(`Found user: ${user.email}`);
} }
let balance = await db.models.Balance.findOne({ user: user._id }).lean(); let balance = await Balance.findOne({ user: user._id }).lean();
if (!balance) { if (!balance) {
console.purple('User has no balance!'); console.purple('User has no balance!');
} else { } else {
@ -85,7 +85,7 @@ const connect = require('./connect');
*/ */
let result; let result;
try { try {
result = await db.models.Balance.findOneAndUpdate( result = await Balance.findOneAndUpdate(
{ user: user._id }, { user: user._id },
{ tokenCredits: amount }, { tokenCredits: amount },
{ upsert: true, new: true }, { upsert: true, new: true },

View file

@ -1,9 +1,9 @@
const path = require('path'); const path = require('path');
const { v5: uuidv5 } = require('uuid'); const { v5: uuidv5 } = require('uuid');
const { Banner } = require('@librechat/data-schemas');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, askMultiLineQuestion, silentExit } = require('./helpers'); const { askQuestion, askMultiLineQuestion, silentExit } = require('./helpers');
const connect = require('./connect'); const connect = require('./connect');
const db = require('~/lib/db/connectDb');
(async () => { (async () => {
await connect(); await connect();
@ -87,7 +87,6 @@ const db = require('~/lib/db/connectDb');
let result; let result;
try { try {
const { Banner } = db.models;
// There is always only one Banner record in the DB. // There is always only one Banner record in the DB.
// If a Banner exists in the DB, it will be updated. // If a Banner exists in the DB, it will be updated.
// If it doesn't exist, a new one will be added. // If it doesn't exist, a new one will be added.

View file

@ -1,7 +1,7 @@
const path = require('path'); const path = require('path');
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') }); require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { silentExit } = require('./helpers'); const { silentExit } = require('./helpers');
const db = require('~/lib/db/connectDb'); const { User, Conversation, Message } = require('@librechat/data-schemas');
const connect = require('./connect'); const connect = require('./connect');
(async () => { (async () => {
@ -14,7 +14,6 @@ const connect = require('./connect');
console.purple('Show the stats of all users'); console.purple('Show the stats of all users');
console.purple('-----------------------------'); console.purple('-----------------------------');
const { User, Conversation, Message } = db.models;
let users = await User.find({}); let users = await User.find({});
let userData = []; let userData = [];
for (const user of users) { for (const user of users) {

View file

@ -1,10 +1,7 @@
// Export all types export { default as logger } from './config/winston';
export { default as meiliLogger } from './config/meiliLogger';
export * from './types'; export * from './types';
// Export all models
export * from './models'; export * from './models';
// Export all methods
export * from './methods'; export * from './methods';
// Export schemas (if needed for direct access) // Export schemas (if needed for direct access)
@ -16,13 +13,10 @@ export { default as tokenSchema } from './schema/token';
export { signPayload, hashToken } from './schema/session'; export { signPayload, hashToken } from './schema/session';
export { default as actionSchema } from './schema/action'; export { default as actionSchema } from './schema/action';
export type { IAction } from './schema/action';
export { default as agentSchema } from './schema/agent'; export { default as agentSchema } from './schema/agent';
export type { IAgent } from './schema/agent';
export { default as assistantSchema } from './schema/assistant'; export { default as assistantSchema } from './schema/assistant';
export type { IAssistant } from './schema/assistant';
export { default as balanceSchema } from './schema/balance'; export { default as balanceSchema } from './schema/balance';
@ -38,10 +32,8 @@ export type { IConversationTag } from './schema/conversationTag';
export { default as convoSchema } from './schema/convo'; export { default as convoSchema } from './schema/convo';
export { default as fileSchema } from './schema/file'; export { default as fileSchema } from './schema/file';
export type { IMongoFile } from './schema/file';
export { default as keySchema } from './schema/key'; export { default as keySchema } from './schema/key';
export type { IKey } from './schema/key';
export { default as messageSchema } from './schema/message'; export { default as messageSchema } from './schema/message';
export type { IMessage } from './schema/message'; export type { IMessage } from './schema/message';
@ -62,7 +54,6 @@ export { default as promptGroupSchema } from './schema/promptGroup';
export type { IPromptGroup, IPromptGroupDocument } from './schema/promptGroup'; export type { IPromptGroup, IPromptGroupDocument } from './schema/promptGroup';
export { default as roleSchema } from './schema/role'; export { default as roleSchema } from './schema/role';
export type { IRole } from './schema/role';
export { default as shareSchema } from './schema/share'; export { default as shareSchema } from './schema/share';
export type { ISharedLink } from './schema/share'; export type { ISharedLink } from './schema/share';

View file

@ -0,0 +1,5 @@
import mongoose from 'mongoose';
import actionSchema from '~/schema/action';
import type { IAction } from '~/types';
export const Action = mongoose.models.Action || mongoose.model<IAction>('Action', actionSchema);

View file

@ -0,0 +1,5 @@
import mongoose from 'mongoose';
import agentSchema from '~/schema/agent';
import type { IAgent } from '~/types';
export const Agent = mongoose.models.Agent || mongoose.model<IAgent>('Agent', agentSchema);

View file

@ -0,0 +1,6 @@
import mongoose from 'mongoose';
import assistantSchema from '~/schema/assistant';
import type { IAssistant } from '~/types';
export const Assistant =
mongoose.models.Assistant || mongoose.model<IAssistant>('Assistant', assistantSchema);

View file

@ -0,0 +1,5 @@
import mongoose from 'mongoose';
import bannerSchema from '~/schema/banner';
import type { IBanner } from '~/types';
export const Banner = mongoose.models.Banner || mongoose.model<IBanner>('Banner', bannerSchema);

View file

@ -0,0 +1,5 @@
import mongoose from 'mongoose';
import fileSchema from '~/schema/file';
import type { IMongoFile } from '~/types';
export const File = mongoose.models.File || mongoose.model<IMongoFile>('File', fileSchema);

View file

@ -5,3 +5,8 @@ export { Session } from './session';
export { Balance } from './balance'; export { Balance } from './balance';
export { Conversation } from './convo'; export { Conversation } from './convo';
export { Message } from './message'; export { Message } from './message';
export { Agent } from './agent';
export { Role } from './role';
export { Action } from './action';
export { Assistant } from './assistant';
export { File } from './file';

View file

@ -1,6 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import mongoose, { Schema, Document, Model, Query } from 'mongoose';
import { MeiliSearch, Index } from 'meilisearch'; import { MeiliSearch, Index } from 'meilisearch';
import mongoose, { Schema, Document, Model, Query } from 'mongoose';
import logger from '~/config/meiliLogger'; import logger from '~/config/meiliLogger';
interface MongoMeiliOptions { interface MongoMeiliOptions {

View file

@ -0,0 +1,5 @@
import mongoose from 'mongoose';
import roleSchema from '~/schema/role';
import type { IRole } from '~/types';
export const Role = mongoose.models.Role || mongoose.model<IRole>('Role', roleSchema);

View file

@ -1,31 +1,5 @@
import mongoose, { Schema, Document } from 'mongoose'; import mongoose, { Schema } from 'mongoose';
import type { IAction } from '~/types';
export interface IAction extends Document {
user: mongoose.Types.ObjectId;
action_id: string;
type: string;
settings?: unknown;
agent_id?: string;
assistant_id?: string;
metadata: {
api_key?: string;
auth: {
authorization_type?: string;
custom_auth_header?: string;
type: 'service_http' | 'oauth' | 'none';
authorization_content_type?: string;
authorization_url?: string;
client_url?: string;
scope?: string;
token_exchange_method: 'default_post' | 'basic_auth_header' | null;
};
domain: string;
privacy_policy_url?: string;
raw_spec?: string;
oauth_client_id?: string;
oauth_client_secret?: string;
};
}
// Define the Auth sub-schema with type-safety. // Define the Auth sub-schema with type-safety.
const AuthSchema = new Schema( const AuthSchema = new Schema(

View file

@ -1,33 +1,5 @@
import { Schema, Document, Types } from 'mongoose'; import { Schema } from 'mongoose';
export interface IAgent extends Omit<Document, 'model'> { import type { IAgent } from '~/types';
id: string;
name?: string;
description?: string;
instructions?: string;
avatar?: {
filepath: string;
source: string;
};
provider: string;
model: string;
model_parameters?: Record<string, unknown>;
artifacts?: string;
access_level?: number;
recursion_limit?: number;
tools?: string[];
tool_kwargs?: Array<unknown>;
actions?: string[];
author: Types.ObjectId;
authorName?: string;
hide_sequential_outputs?: boolean;
end_after_tools?: boolean;
agent_ids?: string[];
isCollaborative?: boolean;
conversation_starters?: string[];
tool_resources?: unknown;
projectIds?: Types.ObjectId[];
versions?: Omit<IAgent, 'versions'>[];
}
const agentSchema = new Schema<IAgent>( const agentSchema = new Schema<IAgent>(
{ {

View file

@ -1,18 +1,5 @@
import { Schema, Document, Types } from 'mongoose'; import { Schema } from 'mongoose';
import type { IAssistant } from '~/types';
export interface IAssistant extends Document {
user: Types.ObjectId;
assistant_id: string;
avatar?: {
filepath: string;
source: string;
};
conversation_starters?: string[];
access_level?: number;
file_ids?: string[];
actions?: string[];
append_current_datetime?: boolean;
}
const assistantSchema = new Schema<IAssistant>( const assistantSchema = new Schema<IAssistant>(
{ {

View file

@ -1,32 +1,6 @@
import mongoose, { Schema, Document, Types } from 'mongoose'; import mongoose, { Schema } from 'mongoose';
import { FileSources } from 'librechat-data-provider'; import { FileSources } from 'librechat-data-provider';
import type { IMongoFile } from '~/types';
// @ts-ignore
export interface IMongoFile extends Document {
user: Types.ObjectId;
conversationId?: string;
file_id: string;
temp_file_id?: string;
bytes: number;
text?: string;
filename: string;
filepath: string;
object: 'file';
embedded?: boolean;
type: string;
context?: string;
usage: number;
source: string;
model?: string;
width?: number;
height?: number;
metadata?: {
fileIdentifier?: string;
};
expiresAt?: Date;
createdAt?: Date;
updatedAt?: Date;
}
const file: Schema<IMongoFile> = new Schema( const file: Schema<IMongoFile> = new Schema(
{ {

View file

@ -1,36 +1,6 @@
import { Schema, Document } from 'mongoose'; import { Schema } from 'mongoose';
import { PermissionTypes, Permissions } from 'librechat-data-provider'; import { PermissionTypes, Permissions } from 'librechat-data-provider';
import type { IRole } from '~/types';
export interface IRole extends Document {
name: string;
permissions: {
[PermissionTypes.BOOKMARKS]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.PROMPTS]?: {
[Permissions.SHARED_GLOBAL]?: boolean;
[Permissions.USE]?: boolean;
[Permissions.CREATE]?: boolean;
};
[PermissionTypes.AGENTS]?: {
[Permissions.SHARED_GLOBAL]?: boolean;
[Permissions.USE]?: boolean;
[Permissions.CREATE]?: boolean;
};
[PermissionTypes.MULTI_CONVO]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.TEMPORARY_CHAT]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.RUN_CODE]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.WEB_SEARCH]?: {
[Permissions.USE]?: boolean;
};
};
}
// Create a sub-schema for permissions. Notice we disable _id for this subdocument. // Create a sub-schema for permissions. Notice we disable _id for this subdocument.
const rolePermissionsSchema = new Schema( const rolePermissionsSchema = new Schema(

View file

@ -0,0 +1,28 @@
import mongoose, { Document } from 'mongoose';
export interface IAction extends Document {
user: mongoose.Types.ObjectId;
action_id: string;
type: string;
settings?: unknown;
agent_id?: string;
assistant_id?: string;
metadata: {
api_key?: string;
auth: {
authorization_type?: string;
custom_auth_header?: string;
type: 'service_http' | 'oauth' | 'none';
authorization_content_type?: string;
authorization_url?: string;
client_url?: string;
scope?: string;
token_exchange_method: 'default_post' | 'basic_auth_header' | null;
};
domain: string;
privacy_policy_url?: string;
raw_spec?: string;
oauth_client_id?: string;
oauth_client_secret?: string;
};
}

View file

@ -0,0 +1,31 @@
import { Document, Types } from 'mongoose';
export interface IAgent extends Omit<Document, 'model'> {
id: string;
name?: string;
description?: string;
instructions?: string;
avatar?: {
filepath: string;
source: string;
};
provider: string;
model: string;
model_parameters?: Record<string, unknown>;
artifacts?: string;
access_level?: number;
recursion_limit?: number;
tools?: string[];
tool_kwargs?: Array<unknown>;
actions?: string[];
author: Types.ObjectId;
authorName?: string;
hide_sequential_outputs?: boolean;
end_after_tools?: boolean;
agent_ids?: string[];
isCollaborative?: boolean;
conversation_starters?: string[];
tool_resources?: unknown;
projectIds?: Types.ObjectId[];
versions?: Omit<IAgent, 'versions'>[];
}

View file

@ -0,0 +1,15 @@
import { Document, Types } from 'mongoose';
export interface IAssistant extends Document {
user: Types.ObjectId;
assistant_id: string;
avatar?: {
filepath: string;
source: string;
};
conversation_starters?: string[];
access_level?: number;
file_ids?: string[];
actions?: string[];
append_current_datetime?: boolean;
}

View file

@ -0,0 +1,10 @@
import type { Document } from 'mongoose';
export interface IBanner extends Document {
bannerId: string;
message: string;
displayFrom: Date;
displayTo?: Date;
type: 'banner' | 'popup';
isPublic: boolean;
}

View file

@ -0,0 +1,27 @@
import { Document, Types } from 'mongoose';
export interface IMongoFile extends Omit<Document, 'model'> {
user: Types.ObjectId;
conversationId?: string;
file_id: string;
temp_file_id?: string;
bytes: number;
text?: string;
filename: string;
filepath: string;
object: 'file';
embedded?: boolean;
type: string;
context?: string;
usage: number;
source: string;
model?: string;
width?: number;
height?: number;
metadata?: {
fileIdentifier?: string;
};
expiresAt?: Date;
createdAt?: Date;
updatedAt?: Date;
}

View file

@ -3,4 +3,10 @@ export * from './token';
export * from './convo'; export * from './convo';
export * from './session'; export * from './session';
export * from './balance'; export * from './balance';
export * from './banner';
export * from './message'; export * from './message';
export * from './agent';
export * from './role';
export * from './action';
export * from './assistant';
export * from './file';

View file

@ -0,0 +1,33 @@
import { Document } from 'mongoose';
import { PermissionTypes, Permissions } from 'librechat-data-provider';
export interface IRole extends Document {
name: string;
permissions: {
[PermissionTypes.BOOKMARKS]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.PROMPTS]?: {
[Permissions.SHARED_GLOBAL]?: boolean;
[Permissions.USE]?: boolean;
[Permissions.CREATE]?: boolean;
};
[PermissionTypes.AGENTS]?: {
[Permissions.SHARED_GLOBAL]?: boolean;
[Permissions.USE]?: boolean;
[Permissions.CREATE]?: boolean;
};
[PermissionTypes.MULTI_CONVO]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.TEMPORARY_CHAT]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.RUN_CODE]?: {
[Permissions.USE]?: boolean;
};
[PermissionTypes.WEB_SEARCH]?: {
[Permissions.USE]?: boolean;
};
};
}