@lobehub/chat 1.77.5 → 1.77.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +1 -1
  4. package/src/database/core/db-adaptor.ts +20 -2
  5. package/src/database/models/__tests__/aiProvider.test.ts +2 -0
  6. package/src/database/models/session.ts +8 -0
  7. package/src/database/models/user.ts +7 -1
  8. package/src/database/server/index.ts +1 -1
  9. package/src/libs/trpc/async/index.ts +11 -1
  10. package/src/libs/trpc/lambda/index.ts +1 -0
  11. package/src/libs/trpc/lambda/serverDatabase.ts +10 -0
  12. package/src/server/routers/async/file.ts +4 -5
  13. package/src/server/routers/async/ragEval.ts +3 -4
  14. package/src/server/routers/lambda/_template.ts +3 -5
  15. package/src/server/routers/lambda/agent.ts +8 -8
  16. package/src/server/routers/lambda/aiModel.ts +5 -5
  17. package/src/server/routers/lambda/aiProvider.test.ts +0 -2
  18. package/src/server/routers/lambda/aiProvider.ts +5 -5
  19. package/src/server/routers/lambda/chunk.ts +18 -15
  20. package/src/server/routers/lambda/exporter.ts +4 -4
  21. package/src/server/routers/lambda/file.ts +5 -5
  22. package/src/server/routers/lambda/importer.ts +3 -3
  23. package/src/server/routers/lambda/knowledgeBase.ts +3 -3
  24. package/src/server/routers/lambda/message.ts +5 -3
  25. package/src/server/routers/lambda/plugin.ts +5 -3
  26. package/src/server/routers/lambda/ragEval.ts +17 -14
  27. package/src/server/routers/lambda/session.ts +6 -4
  28. package/src/server/routers/lambda/sessionGroup.ts +3 -3
  29. package/src/server/routers/lambda/thread.ts +4 -4
  30. package/src/server/routers/lambda/topic.ts +5 -3
  31. package/src/server/routers/lambda/user.ts +7 -7
  32. package/src/server/services/nextAuthUser/index.test.ts +1 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.77.6](https://github.com/lobehub/lobe-chat/compare/v1.77.5...v1.77.6)
6
+
7
+ <sup>Released on **2025-04-01**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor the db to context inject mode.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor the db to context inject mode, closes [#7255](https://github.com/lobehub/lobe-chat/issues/7255) ([ffd0dbc](https://github.com/lobehub/lobe-chat/commit/ffd0dbc))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.77.5](https://github.com/lobehub/lobe-chat/compare/v1.77.4...v1.77.5)
6
31
 
7
32
  <sup>Released on **2025-04-01**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Refactor the db to context inject mode."
6
+ ]
7
+ },
8
+ "date": "2025-04-01",
9
+ "version": "1.77.6"
10
+ },
2
11
  {
3
12
  "children": {},
4
13
  "date": "2025-04-01",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.77.5",
3
+ "version": "1.77.6",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -1,6 +1,24 @@
1
- // import { isDesktop } from '@/const/version';
2
1
  import { getDBInstance } from '@/database/core/web-server';
2
+ import { LobeChatDatabase } from '@/database/type';
3
3
 
4
- // import { getPgliteInstance } from './electron';
4
+ /**
5
+ * 懒加载数据库实例
6
+ * 避免每次模块导入时都初始化数据库
7
+ */
8
+ let cachedDB: LobeChatDatabase | null = null;
9
+
10
+ export const getServerDB = async (): Promise<LobeChatDatabase> => {
11
+ // 如果已经有缓存的实例,直接返回
12
+ if (cachedDB) return cachedDB;
13
+
14
+ try {
15
+ // 根据环境选择合适的数据库实例
16
+ cachedDB = getDBInstance();
17
+ return cachedDB;
18
+ } catch (error) {
19
+ console.error('❌ Failed to initialize database:', error);
20
+ throw error;
21
+ }
22
+ };
5
23
 
6
24
  export const serverDB = getDBInstance();
@@ -4,6 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
5
  import { LobeChatDatabase } from '@/database/type';
6
6
  import { ModelProvider } from '@/libs/agent-runtime';
7
+ import { sleep } from '@/utils/sleep';
7
8
 
8
9
  import { aiProviders, users } from '../../schemas';
9
10
  import { AiProviderModel } from '../aiProvider';
@@ -96,6 +97,7 @@ describe('AiProviderModel', () => {
96
97
  describe('query', () => {
97
98
  it('should query ai providers for the user', async () => {
98
99
  await aiProviderModel.create({ name: 'AiHubMix', source: 'custom', id: 'aihubmix' });
100
+ await sleep(10);
99
101
  await aiProviderModel.create({ name: 'AiHubMix', source: 'custom', id: 'aihubmix-2' });
100
102
 
101
103
  const userGroups = await aiProviderModel.query();
@@ -193,6 +193,14 @@ export class SessionModel {
193
193
  type: 'agent' | 'group';
194
194
  }): Promise<SessionItem> => {
195
195
  return this.db.transaction(async (trx) => {
196
+ if (slug) {
197
+ const existResult = await trx.query.sessions.findFirst({
198
+ where: and(eq(sessions.slug, slug), eq(sessions.userId, this.userId)),
199
+ });
200
+
201
+ if (existResult) return existResult;
202
+ }
203
+
196
204
  const newAgents = await trx
197
205
  .insert(agents)
198
206
  .values({
@@ -85,7 +85,13 @@ export class UserModel {
85
85
  const state = result[0];
86
86
 
87
87
  // Decrypt keyVaults
88
- const decryptKeyVaults = await decryptor(state.settingsKeyVaults, this.userId);
88
+ let decryptKeyVaults = {};
89
+
90
+ try {
91
+ decryptKeyVaults = await decryptor(state.settingsKeyVaults, this.userId);
92
+ } catch {
93
+ /* empty */
94
+ }
89
95
 
90
96
  const settings: DeepPartial<UserSettings> = {
91
97
  defaultAgent: state.settingsDefaultAgent || {},
@@ -1 +1 @@
1
- export { serverDB } from '../core/db-adaptor';
1
+ export { getServerDB, serverDB } from '../core/db-adaptor';
@@ -1,3 +1,5 @@
1
+ import { getServerDB } from '@/database/core/db-adaptor';
2
+
1
3
  import { asyncAuth } from './asyncAuth';
2
4
  import { asyncTrpc } from './init';
3
5
 
@@ -5,6 +7,14 @@ export const publicProcedure = asyncTrpc.procedure;
5
7
 
6
8
  export const asyncRouter = asyncTrpc.router;
7
9
 
8
- export const asyncAuthedProcedure = asyncTrpc.procedure.use(asyncAuth);
10
+ export const asyncAuthedProcedure = asyncTrpc.procedure.use(asyncAuth).use(
11
+ asyncTrpc.middleware(async (opts) => {
12
+ const serverDB = await getServerDB();
13
+
14
+ return opts.next({
15
+ ctx: { serverDB },
16
+ });
17
+ }),
18
+ );
9
19
 
10
20
  export const createAsyncCallerFactory = asyncTrpc.createCallerFactory;
@@ -0,0 +1 @@
1
+ export * from './serverDatabase';
@@ -0,0 +1,10 @@
1
+ import { getServerDB } from '@/database/core/db-adaptor';
2
+ import { trpc } from '@/libs/trpc/init';
3
+
4
+ export const serverDatabase = trpc.middleware(async (opts) => {
5
+ const serverDB = await getServerDB();
6
+
7
+ return opts.next({
8
+ ctx: { serverDB },
9
+ });
10
+ });
@@ -11,7 +11,6 @@ import { ChunkModel } from '@/database/models/chunk';
11
11
  import { EmbeddingModel } from '@/database/models/embedding';
12
12
  import { FileModel } from '@/database/models/file';
13
13
  import { NewChunkItem, NewEmbeddingsItem } from '@/database/schemas';
14
- import { serverDB } from '@/database/server';
15
14
  import { asyncAuthedProcedure, asyncRouter as router } from '@/libs/trpc/async';
16
15
  import { getServerDefaultFilesConfig } from '@/server/globalConfig';
17
16
  import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
@@ -31,11 +30,11 @@ const fileProcedure = asyncAuthedProcedure.use(async (opts) => {
31
30
 
32
31
  return opts.next({
33
32
  ctx: {
34
- asyncTaskModel: new AsyncTaskModel(serverDB, ctx.userId),
35
- chunkModel: new ChunkModel(serverDB, ctx.userId),
33
+ asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
34
+ chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
36
35
  chunkService: new ChunkService(ctx.userId),
37
- embeddingModel: new EmbeddingModel(serverDB, ctx.userId),
38
- fileModel: new FileModel(serverDB, ctx.userId),
36
+ embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
37
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
39
38
  },
40
39
  });
41
40
  });
@@ -7,7 +7,6 @@ import { DEFAULT_EMBEDDING_MODEL, DEFAULT_MODEL } from '@/const/settings';
7
7
  import { ChunkModel } from '@/database/models/chunk';
8
8
  import { EmbeddingModel } from '@/database/models/embedding';
9
9
  import { FileModel } from '@/database/models/file';
10
- import { serverDB } from '@/database/server';
11
10
  import {
12
11
  EvalDatasetRecordModel,
13
12
  EvalEvaluationModel,
@@ -25,13 +24,13 @@ const ragEvalProcedure = asyncAuthedProcedure.use(async (opts) => {
25
24
 
26
25
  return opts.next({
27
26
  ctx: {
28
- chunkModel: new ChunkModel(serverDB, ctx.userId),
27
+ chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
29
28
  chunkService: new ChunkService(ctx.userId),
30
29
  datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
31
- embeddingModel: new EmbeddingModel(serverDB, ctx.userId),
30
+ embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
32
31
  evalRecordModel: new EvaluationRecordModel(ctx.userId),
33
32
  evaluationModel: new EvalEvaluationModel(ctx.userId),
34
- fileModel: new FileModel(serverDB, ctx.userId),
33
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
35
34
  },
36
35
  });
37
36
  });
@@ -2,16 +2,16 @@ import { z } from 'zod';
2
2
 
3
3
  import { SessionGroupModel } from '@/database/models/sessionGroup';
4
4
  import { insertSessionGroupSchema } from '@/database/schemas';
5
- import { serverDB } from '@/database/server';
6
5
  import { authedProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
7
7
  import { SessionGroupItem } from '@/types/session';
8
8
 
9
- const sessionProcedure = authedProcedure.use(async (opts) => {
9
+ const sessionProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
10
10
  const { ctx } = opts;
11
11
 
12
12
  return opts.next({
13
13
  ctx: {
14
- sessionGroupModel: new SessionGroupModel(serverDB, ctx.userId),
14
+ sessionGroupModel: new SessionGroupModel(ctx.serverDB, ctx.userId),
15
15
  },
16
16
  });
17
17
  });
@@ -69,8 +69,6 @@ export const sessionGroupRouter = router({
69
69
  }),
70
70
  )
71
71
  .mutation(async ({ input, ctx }) => {
72
- console.log('sortMap:', input.sortMap);
73
-
74
72
  return ctx.sessionGroupModel.updateOrder(input.sortMap);
75
73
  }),
76
74
  });
@@ -7,22 +7,22 @@ import { FileModel } from '@/database/models/file';
7
7
  import { KnowledgeBaseModel } from '@/database/models/knowledgeBase';
8
8
  import { SessionModel } from '@/database/models/session';
9
9
  import { UserModel } from '@/database/models/user';
10
- import { serverDB } from '@/database/server';
11
10
  import { pino } from '@/libs/logger';
12
11
  import { authedProcedure, router } from '@/libs/trpc';
12
+ import { serverDatabase } from '@/libs/trpc/lambda';
13
13
  import { AgentService } from '@/server/services/agent';
14
14
  import { KnowledgeItem, KnowledgeType } from '@/types/knowledgeBase';
15
15
 
16
- const agentProcedure = authedProcedure.use(async (opts) => {
16
+ const agentProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
17
17
  const { ctx } = opts;
18
18
 
19
19
  return opts.next({
20
20
  ctx: {
21
- agentModel: new AgentModel(serverDB, ctx.userId),
22
- agentService: new AgentService(serverDB, ctx.userId),
23
- fileModel: new FileModel(serverDB, ctx.userId),
24
- knowledgeBaseModel: new KnowledgeBaseModel(serverDB, ctx.userId),
25
- sessionModel: new SessionModel(serverDB, ctx.userId),
21
+ agentModel: new AgentModel(ctx.serverDB, ctx.userId),
22
+ agentService: new AgentService(ctx.serverDB, ctx.userId),
23
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
24
+ knowledgeBaseModel: new KnowledgeBaseModel(ctx.serverDB, ctx.userId),
25
+ sessionModel: new SessionModel(ctx.serverDB, ctx.userId),
26
26
  },
27
27
  });
28
28
  });
@@ -90,7 +90,7 @@ export const agentRouter = router({
90
90
  // if there is no session for user, create one
91
91
  if (!item) {
92
92
  // if there is no user, return default config
93
- const user = await UserModel.findById(serverDB, ctx.userId);
93
+ const user = await UserModel.findById(ctx.serverDB, ctx.userId);
94
94
  if (!user) return DEFAULT_AGENT_CONFIG;
95
95
 
96
96
  const res = await ctx.agentService.createInbox();
@@ -3,8 +3,8 @@ import { z } from 'zod';
3
3
  import { AiModelModel } from '@/database/models/aiModel';
4
4
  import { UserModel } from '@/database/models/user';
5
5
  import { AiInfraRepos } from '@/database/repositories/aiInfra';
6
- import { serverDB } from '@/database/server';
7
6
  import { authedProcedure, router } from '@/libs/trpc';
7
+ import { serverDatabase } from '@/libs/trpc/lambda';
8
8
  import { getServerGlobalConfig } from '@/server/globalConfig';
9
9
  import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
10
10
  import {
@@ -15,7 +15,7 @@ import {
15
15
  } from '@/types/aiModel';
16
16
  import { ProviderConfig } from '@/types/user/settings';
17
17
 
18
- const aiModelProcedure = authedProcedure.use(async (opts) => {
18
+ const aiModelProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
19
19
  const { ctx } = opts;
20
20
 
21
21
  const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
@@ -24,13 +24,13 @@ const aiModelProcedure = authedProcedure.use(async (opts) => {
24
24
  return opts.next({
25
25
  ctx: {
26
26
  aiInfraRepos: new AiInfraRepos(
27
- serverDB,
27
+ ctx.serverDB,
28
28
  ctx.userId,
29
29
  aiProvider as Record<string, ProviderConfig>,
30
30
  ),
31
- aiModelModel: new AiModelModel(serverDB, ctx.userId),
31
+ aiModelModel: new AiModelModel(ctx.serverDB, ctx.userId),
32
32
  gateKeeper,
33
- userModel: new UserModel(serverDB, ctx.userId),
33
+ userModel: new UserModel(ctx.serverDB, ctx.userId),
34
34
  },
35
35
  });
36
36
  });
@@ -1,9 +1,7 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest';
2
2
 
3
3
  import { AiProviderModel } from '@/database/models/aiProvider';
4
- import { UserModel } from '@/database/models/user';
5
4
  import { AiInfraRepos } from '@/database/repositories/aiInfra';
6
- import { serverDB } from '@/database/server';
7
5
  import { getServerGlobalConfig } from '@/server/globalConfig';
8
6
  import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
9
7
  import { AiProviderDetailItem, AiProviderRuntimeState } from '@/types/aiProvider';
@@ -3,8 +3,8 @@ import { z } from 'zod';
3
3
  import { AiProviderModel } from '@/database/models/aiProvider';
4
4
  import { UserModel } from '@/database/models/user';
5
5
  import { AiInfraRepos } from '@/database/repositories/aiInfra';
6
- import { serverDB } from '@/database/server';
7
6
  import { authedProcedure, router } from '@/libs/trpc';
7
+ import { serverDatabase } from '@/libs/trpc/lambda';
8
8
  import { getServerGlobalConfig } from '@/server/globalConfig';
9
9
  import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
10
10
  import {
@@ -16,7 +16,7 @@ import {
16
16
  } from '@/types/aiProvider';
17
17
  import { ProviderConfig } from '@/types/user/settings';
18
18
 
19
- const aiProviderProcedure = authedProcedure.use(async (opts) => {
19
+ const aiProviderProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
20
20
  const { ctx } = opts;
21
21
 
22
22
  const { aiProvider } = await getServerGlobalConfig();
@@ -25,13 +25,13 @@ const aiProviderProcedure = authedProcedure.use(async (opts) => {
25
25
  return opts.next({
26
26
  ctx: {
27
27
  aiInfraRepos: new AiInfraRepos(
28
- serverDB,
28
+ ctx.serverDB,
29
29
  ctx.userId,
30
30
  aiProvider as Record<string, ProviderConfig>,
31
31
  ),
32
- aiProviderModel: new AiProviderModel(serverDB, ctx.userId),
32
+ aiProviderModel: new AiProviderModel(ctx.serverDB, ctx.userId),
33
33
  gateKeeper,
34
- userModel: new UserModel(serverDB, ctx.userId),
34
+ userModel: new UserModel(ctx.serverDB, ctx.userId),
35
35
  },
36
36
  });
37
37
  });
@@ -9,28 +9,31 @@ import { EmbeddingModel } from '@/database/models/embedding';
9
9
  import { FileModel } from '@/database/models/file';
10
10
  import { MessageModel } from '@/database/models/message';
11
11
  import { knowledgeBaseFiles } from '@/database/schemas';
12
- import { serverDB } from '@/database/server';
13
12
  import { authedProcedure, router } from '@/libs/trpc';
13
+ import { serverDatabase } from '@/libs/trpc/lambda';
14
14
  import { keyVaults } from '@/libs/trpc/middleware/keyVaults';
15
15
  import { getServerDefaultFilesConfig } from '@/server/globalConfig';
16
16
  import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
17
17
  import { ChunkService } from '@/server/services/chunk';
18
18
  import { SemanticSearchSchema } from '@/types/rag';
19
19
 
20
- const chunkProcedure = authedProcedure.use(keyVaults).use(async (opts) => {
21
- const { ctx } = opts;
22
-
23
- return opts.next({
24
- ctx: {
25
- asyncTaskModel: new AsyncTaskModel(serverDB, ctx.userId),
26
- chunkModel: new ChunkModel(serverDB, ctx.userId),
27
- chunkService: new ChunkService(ctx.userId),
28
- embeddingModel: new EmbeddingModel(serverDB, ctx.userId),
29
- fileModel: new FileModel(serverDB, ctx.userId),
30
- messageModel: new MessageModel(serverDB, ctx.userId),
31
- },
20
+ const chunkProcedure = authedProcedure
21
+ .use(serverDatabase)
22
+ .use(keyVaults)
23
+ .use(async (opts) => {
24
+ const { ctx } = opts;
25
+
26
+ return opts.next({
27
+ ctx: {
28
+ asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
29
+ chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
30
+ chunkService: new ChunkService(ctx.userId),
31
+ embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
32
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
33
+ messageModel: new MessageModel(ctx.serverDB, ctx.userId),
34
+ },
35
+ });
32
36
  });
33
- });
34
37
 
35
38
  export const chunkRouter = router({
36
39
  createEmbeddingChunksTask: chunkProcedure
@@ -173,7 +176,7 @@ export const chunkRouter = router({
173
176
  let finalFileIds = input.fileIds ?? [];
174
177
 
175
178
  if (input.knowledgeIds && input.knowledgeIds.length > 0) {
176
- const knowledgeFiles = await serverDB.query.knowledgeBaseFiles.findMany({
179
+ const knowledgeFiles = await ctx.serverDB.query.knowledgeBaseFiles.findMany({
177
180
  where: inArray(knowledgeBaseFiles.knowledgeBaseId, input.knowledgeIds),
178
181
  });
179
182
 
@@ -1,13 +1,13 @@
1
1
  import { DrizzleMigrationModel } from '@/database/models/drizzleMigration';
2
2
  import { DataExporterRepos } from '@/database/repositories/dataExporter';
3
- import { serverDB } from '@/database/server';
4
3
  import { authedProcedure, router } from '@/libs/trpc';
4
+ import { serverDatabase } from '@/libs/trpc/lambda';
5
5
  import { ExportDatabaseData } from '@/types/export';
6
6
 
7
- const exportProcedure = authedProcedure.use(async (opts) => {
7
+ const exportProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
8
8
  const { ctx } = opts;
9
- const dataExporterRepos = new DataExporterRepos(serverDB, ctx.userId);
10
- const drizzleMigration = new DrizzleMigrationModel(serverDB);
9
+ const dataExporterRepos = new DataExporterRepos(ctx.serverDB, ctx.userId);
10
+ const drizzleMigration = new DrizzleMigrationModel(ctx.serverDB);
11
11
 
12
12
  return opts.next({
13
13
  ctx: { dataExporterRepos, drizzleMigration },
@@ -5,21 +5,21 @@ import { serverDBEnv } from '@/config/db';
5
5
  import { AsyncTaskModel } from '@/database/models/asyncTask';
6
6
  import { ChunkModel } from '@/database/models/chunk';
7
7
  import { FileModel } from '@/database/models/file';
8
- import { serverDB } from '@/database/server';
9
8
  import { authedProcedure, router } from '@/libs/trpc';
9
+ import { serverDatabase } from '@/libs/trpc/lambda';
10
10
  import { S3 } from '@/server/modules/S3';
11
11
  import { getFullFileUrl } from '@/server/utils/files';
12
12
  import { AsyncTaskStatus, AsyncTaskType } from '@/types/asyncTask';
13
13
  import { FileListItem, QueryFileListSchema, UploadFileSchema } from '@/types/files';
14
14
 
15
- const fileProcedure = authedProcedure.use(async (opts) => {
15
+ const fileProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
16
16
  const { ctx } = opts;
17
17
 
18
18
  return opts.next({
19
19
  ctx: {
20
- asyncTaskModel: new AsyncTaskModel(serverDB, ctx.userId),
21
- chunkModel: new ChunkModel(serverDB, ctx.userId),
22
- fileModel: new FileModel(serverDB, ctx.userId),
20
+ asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
21
+ chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
22
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
23
23
  },
24
24
  });
25
25
  });
@@ -2,15 +2,15 @@ import { TRPCError } from '@trpc/server';
2
2
  import { z } from 'zod';
3
3
 
4
4
  import { DataImporterRepos } from '@/database/repositories/dataImporter';
5
- import { serverDB } from '@/database/server';
6
5
  import { authedProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
7
7
  import { S3 } from '@/server/modules/S3';
8
8
  import { ImportPgDataStructure } from '@/types/export';
9
9
  import { ImportResultData, ImporterEntryData } from '@/types/importer';
10
10
 
11
- const importProcedure = authedProcedure.use(async (opts) => {
11
+ const importProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
12
12
  const { ctx } = opts;
13
- const dataImporterService = new DataImporterRepos(serverDB, ctx.userId);
13
+ const dataImporterService = new DataImporterRepos(ctx.serverDB, ctx.userId);
14
14
 
15
15
  return opts.next({
16
16
  ctx: { dataImporterService },
@@ -2,16 +2,16 @@ import { z } from 'zod';
2
2
 
3
3
  import { KnowledgeBaseModel } from '@/database/models/knowledgeBase';
4
4
  import { insertKnowledgeBasesSchema } from '@/database/schemas';
5
- import { serverDB } from '@/database/server';
6
5
  import { authedProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
7
7
  import { KnowledgeBaseItem } from '@/types/knowledgeBase';
8
8
 
9
- const knowledgeBaseProcedure = authedProcedure.use(async (opts) => {
9
+ const knowledgeBaseProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
10
10
  const { ctx } = opts;
11
11
 
12
12
  return opts.next({
13
13
  ctx: {
14
- knowledgeBaseModel: new KnowledgeBaseModel(serverDB, ctx.userId),
14
+ knowledgeBaseModel: new KnowledgeBaseModel(ctx.serverDB, ctx.userId),
15
15
  },
16
16
  });
17
17
  });
@@ -2,19 +2,20 @@ import { z } from 'zod';
2
2
 
3
3
  import { MessageModel } from '@/database/models/message';
4
4
  import { updateMessagePluginSchema } from '@/database/schemas';
5
- import { serverDB } from '@/database/server';
5
+ import { getServerDB } from '@/database/server';
6
6
  import { authedProcedure, publicProcedure, router } from '@/libs/trpc';
7
+ import { serverDatabase } from '@/libs/trpc/lambda';
7
8
  import { getFullFileUrl } from '@/server/utils/files';
8
9
  import { ChatMessage } from '@/types/message';
9
10
  import { BatchTaskResult } from '@/types/service';
10
11
 
11
12
  type ChatMessageList = ChatMessage[];
12
13
 
13
- const messageProcedure = authedProcedure.use(async (opts) => {
14
+ const messageProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
14
15
  const { ctx } = opts;
15
16
 
16
17
  return opts.next({
17
- ctx: { messageModel: new MessageModel(serverDB, ctx.userId) },
18
+ ctx: { messageModel: new MessageModel(ctx.serverDB, ctx.userId) },
18
19
  });
19
20
  });
20
21
 
@@ -95,6 +96,7 @@ export const messageRouter = router({
95
96
  )
96
97
  .query(async ({ input, ctx }) => {
97
98
  if (!ctx.userId) return [];
99
+ const serverDB = await getServerDB();
98
100
 
99
101
  const messageModel = new MessageModel(serverDB, ctx.userId);
100
102
 
@@ -1,15 +1,16 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  import { PluginModel } from '@/database/models/plugin';
4
- import { serverDB } from '@/database/server';
4
+ import { getServerDB } from '@/database/server';
5
5
  import { authedProcedure, publicProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
6
7
  import { LobeTool } from '@/types/tool';
7
8
 
8
- const pluginProcedure = authedProcedure.use(async (opts) => {
9
+ const pluginProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
9
10
  const { ctx } = opts;
10
11
 
11
12
  return opts.next({
12
- ctx: { pluginModel: new PluginModel(serverDB, ctx.userId) },
13
+ ctx: { pluginModel: new PluginModel(ctx.serverDB, ctx.userId) },
13
14
  });
14
15
  });
15
16
 
@@ -66,6 +67,7 @@ export const pluginRouter = router({
66
67
  getPlugins: publicProcedure.query(async ({ ctx }): Promise<LobeTool[]> => {
67
68
  if (!ctx.userId) return [];
68
69
 
70
+ const serverDB = await getServerDB();
69
71
  const pluginModel = new PluginModel(serverDB, ctx.userId);
70
72
 
71
73
  return pluginModel.query();
@@ -7,7 +7,6 @@ import { z } from 'zod';
7
7
 
8
8
  import { DEFAULT_EMBEDDING_MODEL, DEFAULT_MODEL } from '@/const/settings';
9
9
  import { FileModel } from '@/database/models/file';
10
- import { serverDB } from '@/database/server';
11
10
  import {
12
11
  EvalDatasetModel,
13
12
  EvalDatasetRecordModel,
@@ -15,6 +14,7 @@ import {
15
14
  EvaluationRecordModel,
16
15
  } from '@/database/server/models/ragEval';
17
16
  import { authedProcedure, router } from '@/libs/trpc';
17
+ import { serverDatabase } from '@/libs/trpc/lambda';
18
18
  import { keyVaults } from '@/libs/trpc/middleware/keyVaults';
19
19
  import { S3 } from '@/server/modules/S3';
20
20
  import { createAsyncServerClient } from '@/server/routers/async';
@@ -29,20 +29,23 @@ import {
29
29
  insertEvalEvaluationSchema,
30
30
  } from '@/types/eval';
31
31
 
32
- const ragEvalProcedure = authedProcedure.use(keyVaults).use(async (opts) => {
33
- const { ctx } = opts;
34
-
35
- return opts.next({
36
- ctx: {
37
- datasetModel: new EvalDatasetModel(ctx.userId),
38
- fileModel: new FileModel(serverDB, ctx.userId),
39
- datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
40
- evaluationModel: new EvalEvaluationModel(ctx.userId),
41
- evaluationRecordModel: new EvaluationRecordModel(ctx.userId),
42
- s3: new S3(),
43
- },
32
+ const ragEvalProcedure = authedProcedure
33
+ .use(serverDatabase)
34
+ .use(keyVaults)
35
+ .use(async (opts) => {
36
+ const { ctx } = opts;
37
+
38
+ return opts.next({
39
+ ctx: {
40
+ datasetModel: new EvalDatasetModel(ctx.userId),
41
+ fileModel: new FileModel(ctx.serverDB, ctx.userId),
42
+ datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
43
+ evaluationModel: new EvalEvaluationModel(ctx.userId),
44
+ evaluationRecordModel: new EvaluationRecordModel(ctx.userId),
45
+ s3: new S3(),
46
+ },
47
+ });
44
48
  });
45
- });
46
49
 
47
50
  export const ragEvalRouter = router({
48
51
  createDataset: ragEvalProcedure
@@ -3,21 +3,22 @@ import { z } from 'zod';
3
3
  import { SessionModel } from '@/database/models/session';
4
4
  import { SessionGroupModel } from '@/database/models/sessionGroup';
5
5
  import { insertAgentSchema, insertSessionSchema } from '@/database/schemas';
6
- import { serverDB } from '@/database/server';
6
+ import { getServerDB } from '@/database/server';
7
7
  import { authedProcedure, publicProcedure, router } from '@/libs/trpc';
8
+ import { serverDatabase } from '@/libs/trpc/lambda';
8
9
  import { AgentChatConfigSchema } from '@/types/agent';
9
10
  import { LobeMetaDataSchema } from '@/types/meta';
10
11
  import { BatchTaskResult } from '@/types/service';
11
12
  import { ChatSessionList } from '@/types/session';
12
13
  import { merge } from '@/utils/merge';
13
14
 
14
- const sessionProcedure = authedProcedure.use(async (opts) => {
15
+ const sessionProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
15
16
  const { ctx } = opts;
16
17
 
17
18
  return opts.next({
18
19
  ctx: {
19
- sessionGroupModel: new SessionGroupModel(serverDB, ctx.userId),
20
- sessionModel: new SessionModel(serverDB, ctx.userId),
20
+ sessionGroupModel: new SessionGroupModel(ctx.serverDB, ctx.userId),
21
+ sessionModel: new SessionModel(ctx.serverDB, ctx.userId),
21
22
  },
22
23
  });
23
24
  });
@@ -95,6 +96,7 @@ export const sessionRouter = router({
95
96
  sessions: [],
96
97
  };
97
98
 
99
+ const serverDB = await getServerDB();
98
100
  const sessionModel = new SessionModel(serverDB, ctx.userId);
99
101
 
100
102
  return sessionModel.queryWithGroups();
@@ -2,16 +2,16 @@ import { z } from 'zod';
2
2
 
3
3
  import { SessionGroupModel } from '@/database/models/sessionGroup';
4
4
  import { insertSessionGroupSchema } from '@/database/schemas';
5
- import { serverDB } from '@/database/server';
6
5
  import { authedProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
7
7
  import { SessionGroupItem } from '@/types/session';
8
8
 
9
- const sessionProcedure = authedProcedure.use(async (opts) => {
9
+ const sessionProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
10
10
  const { ctx } = opts;
11
11
 
12
12
  return opts.next({
13
13
  ctx: {
14
- sessionGroupModel: new SessionGroupModel(serverDB, ctx.userId),
14
+ sessionGroupModel: new SessionGroupModel(ctx.serverDB, ctx.userId),
15
15
  },
16
16
  });
17
17
  });
@@ -3,17 +3,17 @@ import { z } from 'zod';
3
3
  import { MessageModel } from '@/database/models/message';
4
4
  import { ThreadModel } from '@/database/models/thread';
5
5
  import { insertThreadSchema } from '@/database/schemas';
6
- import { serverDB } from '@/database/server';
7
6
  import { authedProcedure, router } from '@/libs/trpc';
7
+ import { serverDatabase } from '@/libs/trpc/lambda';
8
8
  import { ThreadItem, createThreadSchema } from '@/types/topic/thread';
9
9
 
10
- const threadProcedure = authedProcedure.use(async (opts) => {
10
+ const threadProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
11
11
  const { ctx } = opts;
12
12
 
13
13
  return opts.next({
14
14
  ctx: {
15
- messageModel: new MessageModel(serverDB, ctx.userId),
16
- threadModel: new ThreadModel(serverDB, ctx.userId),
15
+ messageModel: new MessageModel(ctx.serverDB, ctx.userId),
16
+ threadModel: new ThreadModel(ctx.serverDB, ctx.userId),
17
17
  },
18
18
  });
19
19
  });
@@ -1,15 +1,16 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  import { TopicModel } from '@/database/models/topic';
4
- import { serverDB } from '@/database/server';
4
+ import { getServerDB } from '@/database/server';
5
5
  import { authedProcedure, publicProcedure, router } from '@/libs/trpc';
6
+ import { serverDatabase } from '@/libs/trpc/lambda';
6
7
  import { BatchTaskResult } from '@/types/service';
7
8
 
8
- const topicProcedure = authedProcedure.use(async (opts) => {
9
+ const topicProcedure = authedProcedure.use(serverDatabase).use(async (opts) => {
9
10
  const { ctx } = opts;
10
11
 
11
12
  return opts.next({
12
- ctx: { topicModel: new TopicModel(serverDB, ctx.userId) },
13
+ ctx: { topicModel: new TopicModel(ctx.serverDB, ctx.userId) },
13
14
  });
14
15
  });
15
16
 
@@ -101,6 +102,7 @@ export const topicRouter = router({
101
102
  .query(async ({ input, ctx }) => {
102
103
  if (!ctx.userId) return [];
103
104
 
105
+ const serverDB = await getServerDB();
104
106
  const topicModel = new TopicModel(serverDB, ctx.userId);
105
107
 
106
108
  return topicModel.query(input);
@@ -5,10 +5,10 @@ import { enableClerk } from '@/const/auth';
5
5
  import { MessageModel } from '@/database/models/message';
6
6
  import { SessionModel } from '@/database/models/session';
7
7
  import { UserModel, UserNotFoundError } from '@/database/models/user';
8
- import { serverDB } from '@/database/server';
9
8
  import { ClerkAuth } from '@/libs/clerk-auth';
10
9
  import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
11
10
  import { authedProcedure, router } from '@/libs/trpc';
11
+ import { serverDatabase } from '@/libs/trpc/lambda';
12
12
  import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
13
13
  import { UserService } from '@/server/services/user';
14
14
  import {
@@ -19,12 +19,12 @@ import {
19
19
  } from '@/types/user';
20
20
  import { UserSettings } from '@/types/user/settings';
21
21
 
22
- const userProcedure = authedProcedure.use(async (opts) => {
23
- return opts.next({
22
+ const userProcedure = authedProcedure.use(serverDatabase).use(async ({ ctx, next }) => {
23
+ return next({
24
24
  ctx: {
25
25
  clerkAuth: new ClerkAuth(),
26
- nextAuthDbAdapter: LobeNextAuthDbAdapter(serverDB),
27
- userModel: new UserModel(serverDB, opts.ctx.userId),
26
+ nextAuthDbAdapter: LobeNextAuthDbAdapter(ctx.serverDB),
27
+ userModel: new UserModel(ctx.serverDB, ctx.userId),
28
28
  },
29
29
  });
30
30
  });
@@ -77,10 +77,10 @@ export const userRouter = router({
77
77
  }
78
78
  }
79
79
 
80
- const messageModel = new MessageModel(serverDB, ctx.userId);
80
+ const messageModel = new MessageModel(ctx.serverDB, ctx.userId);
81
81
  const hasMoreThan4Messages = await messageModel.hasMoreThanN(4);
82
82
 
83
- const sessionModel = new SessionModel(serverDB, ctx.userId);
83
+ const sessionModel = new SessionModel(ctx.serverDB, ctx.userId);
84
84
  const hasAnyMessages = await messageModel.hasMoreThanN(0);
85
85
  const hasExtraSession = await sessionModel.hasMoreThanN(1);
86
86
 
@@ -6,7 +6,6 @@ import { UserModel } from '@/database/models/user';
6
6
  import { UserItem } from '@/database/schemas';
7
7
  import { serverDB } from '@/database/server';
8
8
  import { pino } from '@/libs/logger';
9
- import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
10
9
 
11
10
  import { NextAuthUserService } from './index';
12
11
 
@@ -23,7 +22,7 @@ vi.mock('@/database/server');
23
22
  describe('NextAuthUserService', () => {
24
23
  let service: NextAuthUserService;
25
24
 
26
- beforeEach(() => {
25
+ beforeEach(async () => {
27
26
  vi.clearAllMocks();
28
27
  service = new NextAuthUserService();
29
28
  });