mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
🔧 fix: Apply Mongoose Plugin at Model Creation (#7749)
* fix: apply mongoMeili when models are created to use main runtime mongoose * chore: update @librechat/data-schemas version to 0.0.8 * refactor: remove unused useDebounceCodeBlock * fix: ensure setter function is stable and handle numeric conversion in useDebouncedInput * refactor: replace useCallback with useMemo for stable debounced function in useDebouncedInput
This commit is contained in:
parent
be4cf5846c
commit
dff4fcac00
9 changed files with 40 additions and 73 deletions
|
|
@ -1,37 +0,0 @@
|
|||
// client/src/hooks/useDebounceCodeBlock.ts
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { codeBlocksState, codeBlockIdsState } from '~/store/artifacts';
|
||||
import type { CodeBlock } from '~/common';
|
||||
|
||||
export function useDebounceCodeBlock() {
|
||||
const setCodeBlocks = useSetRecoilState(codeBlocksState);
|
||||
const setCodeBlockIds = useSetRecoilState(codeBlockIdsState);
|
||||
|
||||
const updateCodeBlock = useCallback((codeBlock: CodeBlock) => {
|
||||
console.log('Updating code block:', codeBlock);
|
||||
setCodeBlocks((prev) => ({
|
||||
...prev,
|
||||
[codeBlock.id]: codeBlock,
|
||||
}));
|
||||
setCodeBlockIds((prev) =>
|
||||
prev.includes(codeBlock.id) ? prev : [...prev, codeBlock.id],
|
||||
);
|
||||
}, [setCodeBlocks, setCodeBlockIds]);
|
||||
|
||||
const debouncedUpdateCodeBlock = useCallback(
|
||||
debounce((codeBlock: CodeBlock) => {
|
||||
updateCodeBlock(codeBlock);
|
||||
}, 25),
|
||||
[updateCodeBlock],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
debouncedUpdateCodeBlock.cancel();
|
||||
};
|
||||
}, [debouncedUpdateCodeBlock]);
|
||||
|
||||
return debouncedUpdateCodeBlock;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import debounce from 'lodash/debounce';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import type { SetterOrUpdater } from 'recoil';
|
||||
import type { TSetOption } from '~/common';
|
||||
import { defaultDebouncedDelay } from '~/common';
|
||||
|
|
@ -29,10 +29,10 @@ function useDebouncedInput<T = unknown>({
|
|||
|
||||
/** A debounced function to call the passed setOption with the optionKey and new value.
|
||||
*
|
||||
Note: We use useCallback to ensure our debounced function is stable across renders. */
|
||||
const setDebouncedOption = useCallback(
|
||||
debounce(setOption && optionKey ? setOption(optionKey) : setter, delay),
|
||||
[],
|
||||
Note: We use useMemo to ensure our debounced function is stable across renders and properly typed. */
|
||||
const setDebouncedOption = useMemo(
|
||||
() => debounce(setOption && optionKey ? setOption(optionKey) : setter || (() => {}), delay),
|
||||
[setOption, optionKey, setter, delay],
|
||||
);
|
||||
|
||||
/** An onChange handler that updates the local state and the debounced option */
|
||||
|
|
@ -42,8 +42,9 @@ function useDebouncedInput<T = unknown>({
|
|||
typeof e !== 'object'
|
||||
? e
|
||||
: ((e as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>).target
|
||||
.value as unknown as T);
|
||||
if (numeric === true) {
|
||||
.value as unknown as T);
|
||||
// Handle numeric conversion only if value is not undefined and not empty string
|
||||
if (numeric === true && newValue !== undefined && newValue !== '') {
|
||||
newValue = Number(newValue) as unknown as T;
|
||||
}
|
||||
setValue(newValue);
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -46018,7 +46018,7 @@
|
|||
"passport-facebook": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@librechat/data-schemas": "^0.0.7",
|
||||
"@librechat/data-schemas": "^0.0.8",
|
||||
"@rollup/plugin-alias": "^5.1.0",
|
||||
"@rollup/plugin-commonjs": "^25.0.2",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
|
|
@ -46186,7 +46186,7 @@
|
|||
},
|
||||
"packages/data-schemas": {
|
||||
"name": "@librechat/data-schemas",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-alias": "^5.1.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@librechat/data-schemas",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"description": "Mongoose schemas and models for LibreChat",
|
||||
"type": "module",
|
||||
"main": "dist/index.cjs",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
import type * as t from '~/types';
|
||||
import mongoMeili from '~/models/plugins/mongoMeili';
|
||||
import convoSchema from '~/schema/convo';
|
||||
|
||||
/**
|
||||
* Creates or returns the Conversation model using the provided mongoose instance and schema
|
||||
*/
|
||||
export function createConversationModel(mongoose: typeof import('mongoose')) {
|
||||
if (process.env.MEILI_HOST && process.env.MEILI_MASTER_KEY) {
|
||||
convoSchema.plugin(mongoMeili, {
|
||||
mongoose,
|
||||
host: process.env.MEILI_HOST,
|
||||
apiKey: process.env.MEILI_MASTER_KEY,
|
||||
/** Note: Will get created automatically if it doesn't exist already */
|
||||
indexName: 'convos',
|
||||
primaryKey: 'conversationId',
|
||||
});
|
||||
}
|
||||
return (
|
||||
mongoose.models.Conversation || mongoose.model<t.IConversation>('Conversation', convoSchema)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
import messageSchema from '~/schema/message';
|
||||
import type * as t from '~/types';
|
||||
import mongoMeili from '~/models/plugins/mongoMeili';
|
||||
import messageSchema from '~/schema/message';
|
||||
|
||||
/**
|
||||
* Creates or returns the Message model using the provided mongoose instance and schema
|
||||
*/
|
||||
export function createMessageModel(mongoose: typeof import('mongoose')) {
|
||||
if (process.env.MEILI_HOST && process.env.MEILI_MASTER_KEY) {
|
||||
messageSchema.plugin(mongoMeili, {
|
||||
mongoose,
|
||||
host: process.env.MEILI_HOST,
|
||||
apiKey: process.env.MEILI_MASTER_KEY,
|
||||
indexName: 'messages',
|
||||
primaryKey: 'messageId',
|
||||
});
|
||||
}
|
||||
|
||||
return mongoose.models.Message || mongoose.model<t.IMessage>('Message', messageSchema);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import _ from 'lodash';
|
||||
import { MeiliSearch, Index } from 'meilisearch';
|
||||
import mongoose, { Schema, Document, Model, Query } from 'mongoose';
|
||||
import type { FilterQuery, Types, Schema, Document, Model, Query } from 'mongoose';
|
||||
import logger from '~/config/meiliLogger';
|
||||
|
||||
interface MongoMeiliOptions {
|
||||
|
|
@ -8,6 +8,7 @@ interface MongoMeiliOptions {
|
|||
apiKey: string;
|
||||
indexName: string;
|
||||
primaryKey: string;
|
||||
mongoose: typeof import('mongoose');
|
||||
}
|
||||
|
||||
interface MeiliIndexable {
|
||||
|
|
@ -314,7 +315,7 @@ const createMeiliMongooseModel = ({
|
|||
}
|
||||
|
||||
await this.collection.updateMany(
|
||||
{ _id: this._id as mongoose.Types.ObjectId },
|
||||
{ _id: this._id as Types.ObjectId },
|
||||
{ $set: { _meiliIndex: true } },
|
||||
);
|
||||
}
|
||||
|
|
@ -398,6 +399,7 @@ const createMeiliMongooseModel = ({
|
|||
* @param options.primaryKey - The primary key field for indexing.
|
||||
*/
|
||||
export default function mongoMeili(schema: Schema, options: MongoMeiliOptions): void {
|
||||
const mongoose = options.mongoose;
|
||||
validateOptions(options);
|
||||
|
||||
// Add _meiliIndex field to the schema to track if a document has been indexed in MeiliSearch.
|
||||
|
|
@ -452,7 +454,7 @@ export default function mongoMeili(schema: Schema, options: MongoMeiliOptions):
|
|||
const convoIndex = client.index('convos');
|
||||
const deletedConvos = await mongoose
|
||||
.model('Conversation')
|
||||
.find(conditions as mongoose.FilterQuery<unknown>)
|
||||
.find(conditions as FilterQuery<unknown>)
|
||||
.lean();
|
||||
const promises = deletedConvos.map((convo: Record<string, unknown>) =>
|
||||
convoIndex.deleteDocument(convo.conversationId as string),
|
||||
|
|
@ -464,7 +466,7 @@ export default function mongoMeili(schema: Schema, options: MongoMeiliOptions):
|
|||
const messageIndex = client.index('messages');
|
||||
const deletedMessages = await mongoose
|
||||
.model('Message')
|
||||
.find(conditions as mongoose.FilterQuery<unknown>)
|
||||
.find(conditions as FilterQuery<unknown>)
|
||||
.lean();
|
||||
const promises = deletedMessages.map((message: Record<string, unknown>) =>
|
||||
messageIndex.deleteDocument(message.messageId as string),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Schema } from 'mongoose';
|
||||
import mongoMeili from '~/models/plugins/mongoMeili';
|
||||
import { conversationPreset } from './defaults';
|
||||
import { IConversation } from '~/types';
|
||||
|
||||
|
|
@ -48,14 +47,4 @@ convoSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|||
convoSchema.index({ createdAt: 1, updatedAt: 1 });
|
||||
convoSchema.index({ conversationId: 1, user: 1 }, { unique: true });
|
||||
|
||||
if (process.env.MEILI_HOST && process.env.MEILI_MASTER_KEY) {
|
||||
convoSchema.plugin(mongoMeili, {
|
||||
host: process.env.MEILI_HOST,
|
||||
apiKey: process.env.MEILI_MASTER_KEY,
|
||||
/** Note: Will get created automatically if it doesn't exist already */
|
||||
indexName: 'convos',
|
||||
primaryKey: 'conversationId',
|
||||
});
|
||||
}
|
||||
|
||||
export default convoSchema;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import mongoose, { Schema } from 'mongoose';
|
||||
import type { IMessage } from '~/types/message';
|
||||
import mongoMeili from '~/models/plugins/mongoMeili';
|
||||
|
||||
const messageSchema: Schema<IMessage> = new Schema(
|
||||
{
|
||||
|
|
@ -166,13 +165,4 @@ messageSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|||
messageSchema.index({ createdAt: 1 });
|
||||
messageSchema.index({ messageId: 1, user: 1 }, { unique: true });
|
||||
|
||||
if (process.env.MEILI_HOST && process.env.MEILI_MASTER_KEY) {
|
||||
messageSchema.plugin(mongoMeili, {
|
||||
host: process.env.MEILI_HOST,
|
||||
apiKey: process.env.MEILI_MASTER_KEY,
|
||||
indexName: 'messages',
|
||||
primaryKey: 'messageId',
|
||||
});
|
||||
}
|
||||
|
||||
export default messageSchema;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue