@lobehub/chat 1.74.2 → 1.74.4
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.
- package/CHANGELOG.md +58 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/changelog/v1.json +18 -0
- package/docs/developer/database-schema.dbml +54 -2
- package/locales/ar/common.json +51 -0
- package/locales/ar/models.json +69 -3
- package/locales/ar/providers.json +6 -0
- package/locales/bg-BG/common.json +51 -0
- package/locales/bg-BG/models.json +69 -3
- package/locales/bg-BG/providers.json +6 -0
- package/locales/de-DE/common.json +51 -0
- package/locales/de-DE/models.json +69 -3
- package/locales/de-DE/providers.json +6 -0
- package/locales/en-US/common.json +51 -0
- package/locales/en-US/models.json +69 -3
- package/locales/en-US/providers.json +6 -3
- package/locales/es-ES/common.json +51 -0
- package/locales/es-ES/models.json +69 -3
- package/locales/es-ES/providers.json +6 -0
- package/locales/fa-IR/common.json +51 -0
- package/locales/fa-IR/models.json +69 -3
- package/locales/fa-IR/providers.json +6 -0
- package/locales/fr-FR/common.json +51 -0
- package/locales/fr-FR/models.json +69 -3
- package/locales/fr-FR/providers.json +6 -0
- package/locales/it-IT/common.json +51 -0
- package/locales/it-IT/models.json +69 -3
- package/locales/it-IT/providers.json +6 -0
- package/locales/ja-JP/common.json +51 -0
- package/locales/ja-JP/models.json +78 -4
- package/locales/ja-JP/providers.json +6 -0
- package/locales/ko-KR/common.json +51 -0
- package/locales/ko-KR/models.json +69 -3
- package/locales/ko-KR/providers.json +6 -0
- package/locales/nl-NL/common.json +51 -0
- package/locales/nl-NL/models.json +69 -3
- package/locales/nl-NL/providers.json +6 -0
- package/locales/pl-PL/common.json +51 -0
- package/locales/pl-PL/models.json +69 -3
- package/locales/pl-PL/providers.json +6 -0
- package/locales/pt-BR/common.json +51 -0
- package/locales/pt-BR/models.json +69 -3
- package/locales/pt-BR/providers.json +6 -0
- package/locales/ru-RU/common.json +51 -0
- package/locales/ru-RU/models.json +69 -3
- package/locales/ru-RU/providers.json +6 -0
- package/locales/tr-TR/common.json +51 -0
- package/locales/tr-TR/models.json +69 -3
- package/locales/tr-TR/providers.json +6 -0
- package/locales/vi-VN/common.json +51 -0
- package/locales/vi-VN/models.json +69 -3
- package/locales/vi-VN/providers.json +6 -0
- package/locales/zh-CN/common.json +53 -2
- package/locales/zh-CN/models.json +79 -13
- package/locales/zh-CN/providers.json +6 -4
- package/locales/zh-TW/common.json +51 -0
- package/locales/zh-TW/models.json +81 -4
- package/locales/zh-TW/providers.json +6 -0
- package/package.json +5 -5
- package/packages/web-crawler/src/utils/__tests__/withTimeout.test.ts +0 -1
- package/packages/web-crawler/src/utils/html/yingchao.html +0 -16
- package/packages/web-crawler/src/utils/htmlToMarkdown.test.ts +1 -1
- package/src/app/(backend)/webapi/plugin/store/route.ts +6 -2
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +4 -0
- package/src/database/client/db.ts +102 -11
- package/src/database/client/migrations.json +38 -8
- package/src/database/migrations/0018_add_client_id_for_entities.sql +32 -0
- package/src/database/migrations/meta/0018_snapshot.json +4212 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/models/drizzleMigration.ts +23 -0
- package/src/database/schemas/agent.ts +48 -31
- package/src/database/schemas/file.ts +32 -16
- package/src/database/schemas/message.ts +91 -54
- package/src/database/schemas/rag.ts +65 -32
- package/src/database/schemas/session.ts +6 -3
- package/src/database/schemas/topic.ts +31 -24
- package/src/features/InitClientDB/ErrorResult.tsx +53 -32
- package/src/features/InitClientDB/features/DatabaseRepair/Backup.tsx +77 -0
- package/src/features/InitClientDB/features/DatabaseRepair/Diagnosis.tsx +98 -0
- package/src/features/InitClientDB/features/DatabaseRepair/Repair.tsx +220 -0
- package/src/features/InitClientDB/features/DatabaseRepair/index.tsx +85 -0
- package/src/features/ModelSwitchPanel/index.tsx +13 -7
- package/src/locales/default/common.ts +53 -1
- package/src/store/global/actions/clientDb.ts +19 -3
- package/src/store/global/initialState.ts +6 -1
- package/src/store/global/selectors/clientDB.ts +43 -0
- package/src/store/global/selectors/index.ts +1 -0
- package/src/store/user/slices/settings/selectors/general.test.ts +90 -0
- package/src/types/clientDB.ts +13 -0
@@ -126,6 +126,13 @@
|
|
126
126
|
"when": 1742269437903,
|
127
127
|
"tag": "0017_add_user_id_to_tables",
|
128
128
|
"breakpoints": true
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"idx": 18,
|
132
|
+
"version": "7",
|
133
|
+
"when": 1742616026643,
|
134
|
+
"tag": "0018_add_client_id_for_entities",
|
135
|
+
"breakpoints": true
|
129
136
|
}
|
130
137
|
],
|
131
138
|
"version": "6"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { LobeChatDatabase } from '@/database/type';
|
2
|
+
import { MigrationTableItem } from '@/types/clientDB';
|
3
|
+
|
4
|
+
export class DrizzleMigrationModel {
|
5
|
+
private db: LobeChatDatabase;
|
6
|
+
|
7
|
+
constructor(db: LobeChatDatabase) {
|
8
|
+
this.db = db;
|
9
|
+
}
|
10
|
+
|
11
|
+
getMigrationList = async () => {
|
12
|
+
const res = await this.db.execute(
|
13
|
+
'SELECT * FROM "drizzle"."__drizzle_migrations" ORDER BY "created_at" DESC;',
|
14
|
+
);
|
15
|
+
|
16
|
+
return res.rows as unknown as MigrationTableItem[];
|
17
|
+
};
|
18
|
+
getLatestMigrationHash = async () => {
|
19
|
+
const res = await this.getMigrationList();
|
20
|
+
|
21
|
+
return res[0].hash;
|
22
|
+
};
|
23
|
+
}
|
@@ -1,5 +1,13 @@
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
boolean,
|
4
|
+
jsonb,
|
5
|
+
pgTable,
|
6
|
+
primaryKey,
|
7
|
+
text,
|
8
|
+
uniqueIndex,
|
9
|
+
varchar,
|
10
|
+
} from 'drizzle-orm/pg-core';
|
3
11
|
import { createInsertSchema } from 'drizzle-zod';
|
4
12
|
|
5
13
|
import { idGenerator, randomSlug } from '@/database/utils/idGenerator';
|
@@ -13,36 +21,45 @@ import { users } from './user';
|
|
13
21
|
// agent is a model that represents the assistant that is created by the user
|
14
22
|
// agent can have its own knowledge base and files
|
15
23
|
|
16
|
-
export const agents = pgTable(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
24
|
+
export const agents = pgTable(
|
25
|
+
'agents',
|
26
|
+
{
|
27
|
+
id: text('id')
|
28
|
+
.primaryKey()
|
29
|
+
.$defaultFn(() => idGenerator('agents'))
|
30
|
+
.notNull(),
|
31
|
+
slug: varchar('slug', { length: 100 })
|
32
|
+
.$defaultFn(() => randomSlug(4))
|
33
|
+
.unique(),
|
34
|
+
title: text('title'),
|
35
|
+
description: text('description'),
|
36
|
+
tags: jsonb('tags').$type<string[]>().default([]),
|
37
|
+
avatar: text('avatar'),
|
38
|
+
backgroundColor: text('background_color'),
|
39
|
+
|
40
|
+
plugins: jsonb('plugins').$type<string[]>().default([]),
|
41
|
+
|
42
|
+
clientId: text('client_id'),
|
43
|
+
|
44
|
+
userId: text('user_id')
|
45
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
46
|
+
.notNull(),
|
47
|
+
|
48
|
+
chatConfig: jsonb('chat_config').$type<LobeAgentChatConfig>(),
|
49
|
+
|
50
|
+
fewShots: jsonb('few_shots'),
|
51
|
+
model: text('model'),
|
52
|
+
params: jsonb('params').default({}),
|
53
|
+
provider: text('provider'),
|
54
|
+
systemRole: text('system_role'),
|
55
|
+
tts: jsonb('tts').$type<LobeAgentTTSConfig>(),
|
56
|
+
|
57
|
+
...timestamps,
|
58
|
+
},
|
59
|
+
(t) => ({
|
60
|
+
clientIdUnique: uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId),
|
61
|
+
}),
|
62
|
+
);
|
46
63
|
|
47
64
|
export const insertAgentSchema = createInsertSchema(agents);
|
48
65
|
|
@@ -7,6 +7,7 @@ import {
|
|
7
7
|
pgTable,
|
8
8
|
primaryKey,
|
9
9
|
text,
|
10
|
+
uniqueIndex,
|
10
11
|
uuid,
|
11
12
|
varchar,
|
12
13
|
} from 'drizzle-orm/pg-core';
|
@@ -52,6 +53,7 @@ export const files = pgTable(
|
|
52
53
|
size: integer('size').notNull(),
|
53
54
|
url: text('url').notNull(),
|
54
55
|
|
56
|
+
clientId: text('client_id'),
|
55
57
|
metadata: jsonb('metadata'),
|
56
58
|
chunkTaskId: uuid('chunk_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
|
57
59
|
embeddingTaskId: uuid('embedding_task_id').references(() => asyncTasks.id, {
|
@@ -63,33 +65,47 @@ export const files = pgTable(
|
|
63
65
|
(table) => {
|
64
66
|
return {
|
65
67
|
fileHashIdx: index('file_hash_idx').on(table.fileHash),
|
68
|
+
clientIdUnique: uniqueIndex('files_client_id_user_id_unique').on(
|
69
|
+
table.clientId,
|
70
|
+
table.userId,
|
71
|
+
),
|
66
72
|
};
|
67
73
|
},
|
68
74
|
);
|
69
75
|
export type NewFile = typeof files.$inferInsert;
|
70
76
|
export type FileItem = typeof files.$inferSelect;
|
71
77
|
|
72
|
-
export const knowledgeBases = pgTable(
|
73
|
-
|
74
|
-
|
75
|
-
|
78
|
+
export const knowledgeBases = pgTable(
|
79
|
+
'knowledge_bases',
|
80
|
+
{
|
81
|
+
id: text('id')
|
82
|
+
.$defaultFn(() => idGenerator('knowledgeBases'))
|
83
|
+
.primaryKey(),
|
76
84
|
|
77
|
-
|
78
|
-
|
79
|
-
|
85
|
+
name: text('name').notNull(),
|
86
|
+
description: text('description'),
|
87
|
+
avatar: text('avatar'),
|
80
88
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
// different types of knowledge bases need to be distinguished
|
90
|
+
type: text('type'),
|
91
|
+
userId: text('user_id')
|
92
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
93
|
+
.notNull(),
|
94
|
+
clientId: text('client_id'),
|
86
95
|
|
87
|
-
|
96
|
+
isPublic: boolean('is_public').default(false),
|
88
97
|
|
89
|
-
|
98
|
+
settings: jsonb('settings'),
|
90
99
|
|
91
|
-
|
92
|
-
}
|
100
|
+
...timestamps,
|
101
|
+
},
|
102
|
+
(t) => ({
|
103
|
+
clientIdUnique: uniqueIndex('knowledge_bases_client_id_user_id_unique').on(
|
104
|
+
t.clientId,
|
105
|
+
t.userId,
|
106
|
+
),
|
107
|
+
}),
|
108
|
+
);
|
93
109
|
|
94
110
|
export const insertKnowledgeBasesSchema = createInsertSchema(knowledgeBases);
|
95
111
|
|
@@ -80,52 +80,79 @@ export const messages = pgTable(
|
|
80
80
|
);
|
81
81
|
|
82
82
|
// if the message container a plugin
|
83
|
-
export const messagePlugins = pgTable(
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
83
|
+
export const messagePlugins = pgTable(
|
84
|
+
'message_plugins',
|
85
|
+
{
|
86
|
+
id: text('id')
|
87
|
+
.references(() => messages.id, { onDelete: 'cascade' })
|
88
|
+
.primaryKey(),
|
89
|
+
|
90
|
+
toolCallId: text('tool_call_id'),
|
91
|
+
type: text('type', {
|
92
|
+
enum: ['default', 'markdown', 'standalone', 'builtin'],
|
93
|
+
}).default('default'),
|
94
|
+
|
95
|
+
apiName: text('api_name'),
|
96
|
+
arguments: text('arguments'),
|
97
|
+
identifier: text('identifier'),
|
98
|
+
state: jsonb('state'),
|
99
|
+
error: jsonb('error'),
|
100
|
+
clientId: text('client_id'),
|
101
|
+
userId: text('user_id')
|
102
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
103
|
+
.notNull(),
|
104
|
+
},
|
105
|
+
(t) => ({
|
106
|
+
clientIdUnique: uniqueIndex('message_plugins_client_id_user_id_unique').on(
|
107
|
+
t.clientId,
|
108
|
+
t.userId,
|
109
|
+
),
|
110
|
+
}),
|
111
|
+
);
|
102
112
|
|
103
113
|
export type MessagePluginItem = typeof messagePlugins.$inferSelect;
|
104
114
|
export const updateMessagePluginSchema = createSelectSchema(messagePlugins);
|
105
115
|
|
106
|
-
export const messageTTS = pgTable(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
.
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
116
|
+
export const messageTTS = pgTable(
|
117
|
+
'message_tts',
|
118
|
+
{
|
119
|
+
id: text('id')
|
120
|
+
.references(() => messages.id, { onDelete: 'cascade' })
|
121
|
+
.primaryKey(),
|
122
|
+
contentMd5: text('content_md5'),
|
123
|
+
fileId: text('file_id').references(() => files.id, { onDelete: 'cascade' }),
|
124
|
+
voice: text('voice'),
|
125
|
+
clientId: text('client_id'),
|
126
|
+
userId: text('user_id')
|
127
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
128
|
+
.notNull(),
|
129
|
+
},
|
130
|
+
(t) => ({
|
131
|
+
clientIdUnique: uniqueIndex('message_tts_client_id_user_id_unique').on(t.clientId, t.userId),
|
132
|
+
}),
|
133
|
+
);
|
134
|
+
|
135
|
+
export const messageTranslates = pgTable(
|
136
|
+
'message_translates',
|
137
|
+
{
|
138
|
+
id: text('id')
|
139
|
+
.references(() => messages.id, { onDelete: 'cascade' })
|
140
|
+
.primaryKey(),
|
141
|
+
content: text('content'),
|
142
|
+
from: text('from'),
|
143
|
+
to: text('to'),
|
144
|
+
clientId: text('client_id'),
|
145
|
+
userId: text('user_id')
|
146
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
147
|
+
.notNull(),
|
148
|
+
},
|
149
|
+
(t) => ({
|
150
|
+
clientIdUnique: uniqueIndex('message_translates_client_id_user_id_unique').on(
|
151
|
+
t.clientId,
|
152
|
+
t.userId,
|
153
|
+
),
|
154
|
+
}),
|
155
|
+
);
|
129
156
|
|
130
157
|
// if the message contains a file
|
131
158
|
// save the file id and message id
|
@@ -147,18 +174,28 @@ export const messagesFiles = pgTable(
|
|
147
174
|
}),
|
148
175
|
);
|
149
176
|
|
150
|
-
export const messageQueries = pgTable(
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
})
|
177
|
+
export const messageQueries = pgTable(
|
178
|
+
'message_queries',
|
179
|
+
{
|
180
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
181
|
+
messageId: text('message_id')
|
182
|
+
.references(() => messages.id, { onDelete: 'cascade' })
|
183
|
+
.notNull(),
|
184
|
+
rewriteQuery: text('rewrite_query'),
|
185
|
+
userQuery: text('user_query'),
|
186
|
+
clientId: text('client_id'),
|
187
|
+
userId: text('user_id')
|
188
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
189
|
+
.notNull(),
|
190
|
+
embeddingsId: uuid('embeddings_id').references(() => embeddings.id, { onDelete: 'set null' }),
|
191
|
+
},
|
192
|
+
(t) => ({
|
193
|
+
clientIdUnique: uniqueIndex('message_queries_client_id_user_id_unique').on(
|
194
|
+
t.clientId,
|
195
|
+
t.userId,
|
196
|
+
),
|
197
|
+
}),
|
198
|
+
);
|
162
199
|
|
163
200
|
export type NewMessageQuery = typeof messageQueries.$inferInsert;
|
164
201
|
|
@@ -1,51 +1,84 @@
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
integer,
|
4
|
+
jsonb,
|
5
|
+
pgTable,
|
6
|
+
text,
|
7
|
+
uniqueIndex,
|
8
|
+
uuid,
|
9
|
+
varchar,
|
10
|
+
vector,
|
11
|
+
} from 'drizzle-orm/pg-core';
|
3
12
|
|
4
13
|
import { timestamps } from './_helpers';
|
5
14
|
import { files } from './file';
|
6
15
|
import { users } from './user';
|
7
16
|
|
8
|
-
export const chunks = pgTable(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
export const chunks = pgTable(
|
18
|
+
'chunks',
|
19
|
+
{
|
20
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
21
|
+
text: text('text'),
|
22
|
+
abstract: text('abstract'),
|
23
|
+
metadata: jsonb('metadata'),
|
24
|
+
index: integer('index'),
|
25
|
+
type: varchar('type'),
|
15
26
|
|
16
|
-
|
27
|
+
clientId: text('client_id'),
|
28
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
17
29
|
|
18
|
-
|
19
|
-
}
|
30
|
+
...timestamps,
|
31
|
+
},
|
32
|
+
(t) => ({
|
33
|
+
clientIdUnique: uniqueIndex('chunks_client_id_user_id_unique').on(t.clientId, t.userId),
|
34
|
+
}),
|
35
|
+
);
|
20
36
|
|
21
37
|
export type NewChunkItem = typeof chunks.$inferInsert & { fileId?: string };
|
22
38
|
|
23
|
-
export const unstructuredChunks = pgTable(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
39
|
+
export const unstructuredChunks = pgTable(
|
40
|
+
'unstructured_chunks',
|
41
|
+
{
|
42
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
43
|
+
text: text('text'),
|
44
|
+
metadata: jsonb('metadata'),
|
45
|
+
index: integer('index'),
|
46
|
+
type: varchar('type'),
|
29
47
|
|
30
|
-
|
48
|
+
...timestamps,
|
31
49
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
})
|
50
|
+
parentId: varchar('parent_id'),
|
51
|
+
compositeId: uuid('composite_id').references(() => chunks.id, { onDelete: 'cascade' }),
|
52
|
+
clientId: text('client_id'),
|
53
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
54
|
+
fileId: varchar('file_id').references(() => files.id, { onDelete: 'cascade' }),
|
55
|
+
},
|
56
|
+
(t) => ({
|
57
|
+
clientIdUnique: uniqueIndex('unstructured_chunks_client_id_user_id_unique').on(
|
58
|
+
t.clientId,
|
59
|
+
t.userId,
|
60
|
+
),
|
61
|
+
}),
|
62
|
+
);
|
37
63
|
|
38
64
|
export type NewUnstructuredChunkItem = typeof unstructuredChunks.$inferInsert;
|
39
65
|
|
40
|
-
export const embeddings = pgTable(
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
66
|
+
export const embeddings = pgTable(
|
67
|
+
'embeddings',
|
68
|
+
{
|
69
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
70
|
+
chunkId: uuid('chunk_id')
|
71
|
+
.references(() => chunks.id, { onDelete: 'cascade' })
|
72
|
+
.unique(),
|
73
|
+
embeddings: vector('embeddings', { dimensions: 1024 }),
|
74
|
+
model: text('model'),
|
75
|
+
clientId: text('client_id'),
|
76
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
77
|
+
},
|
78
|
+
(t) => ({
|
79
|
+
clientIdUnique: uniqueIndex('embeddings_client_id_user_id_unique').on(t.clientId, t.userId),
|
80
|
+
}),
|
81
|
+
);
|
49
82
|
|
50
83
|
export type NewEmbeddingsItem = typeof embeddings.$inferInsert;
|
51
84
|
export type EmbeddingsSelectItem = typeof embeddings.$inferSelect;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
2
|
-
import { boolean, integer, pgTable, text,
|
2
|
+
import { boolean, integer, pgTable, text, uniqueIndex, varchar } from 'drizzle-orm/pg-core';
|
3
3
|
import { createInsertSchema } from 'drizzle-zod';
|
4
4
|
|
5
5
|
import { idGenerator, randomSlug } from '@/database/utils/idGenerator';
|
@@ -26,7 +26,10 @@ export const sessionGroups = pgTable(
|
|
26
26
|
...timestamps,
|
27
27
|
},
|
28
28
|
(table) => ({
|
29
|
-
clientIdUnique:
|
29
|
+
clientIdUnique: uniqueIndex('session_groups_client_id_user_id_unique').on(
|
30
|
+
table.clientId,
|
31
|
+
table.userId,
|
32
|
+
),
|
30
33
|
}),
|
31
34
|
);
|
32
35
|
|
@@ -65,7 +68,7 @@ export const sessions = pgTable(
|
|
65
68
|
(t) => ({
|
66
69
|
slugUserIdUnique: uniqueIndex('slug_user_id_unique').on(t.slug, t.userId),
|
67
70
|
|
68
|
-
clientIdUnique:
|
71
|
+
clientIdUnique: uniqueIndex('sessions_client_id_user_id_unique').on(t.clientId, t.userId),
|
69
72
|
}),
|
70
73
|
);
|
71
74
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
2
|
-
import { boolean, jsonb, pgTable, text,
|
2
|
+
import { boolean, jsonb, pgTable, text, uniqueIndex } from 'drizzle-orm/pg-core';
|
3
3
|
import { createInsertSchema } from 'drizzle-zod';
|
4
4
|
|
5
5
|
import { idGenerator } from '@/database/utils/idGenerator';
|
@@ -27,7 +27,7 @@ export const topics = pgTable(
|
|
27
27
|
...timestamps,
|
28
28
|
},
|
29
29
|
(t) => ({
|
30
|
-
clientIdUnique:
|
30
|
+
clientIdUnique: uniqueIndex('topics_client_id_user_id_unique').on(t.clientId, t.userId),
|
31
31
|
}),
|
32
32
|
);
|
33
33
|
|
@@ -35,28 +35,35 @@ export type NewTopic = typeof topics.$inferInsert;
|
|
35
35
|
export type TopicItem = typeof topics.$inferSelect;
|
36
36
|
|
37
37
|
// @ts-ignore
|
38
|
-
export const threads = pgTable(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
38
|
+
export const threads = pgTable(
|
39
|
+
'threads',
|
40
|
+
{
|
41
|
+
id: text('id')
|
42
|
+
.$defaultFn(() => idGenerator('threads', 16))
|
43
|
+
.primaryKey(),
|
44
|
+
|
45
|
+
title: text('title'),
|
46
|
+
type: text('type', { enum: ['continuation', 'standalone'] }).notNull(),
|
47
|
+
status: text('status', { enum: ['active', 'deprecated', 'archived'] }).default('active'),
|
48
|
+
topicId: text('topic_id')
|
49
|
+
.references(() => topics.id, { onDelete: 'cascade' })
|
50
|
+
.notNull(),
|
51
|
+
sourceMessageId: text('source_message_id').notNull(),
|
52
|
+
// @ts-ignore
|
53
|
+
parentThreadId: text('parent_thread_id').references(() => threads.id, { onDelete: 'set null' }),
|
54
|
+
clientId: text('client_id'),
|
55
|
+
|
56
|
+
userId: text('user_id')
|
57
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
58
|
+
.notNull(),
|
59
|
+
|
60
|
+
lastActiveAt: timestamptz('last_active_at').defaultNow(),
|
61
|
+
...timestamps,
|
62
|
+
},
|
63
|
+
(t) => ({
|
64
|
+
clientIdUnique: uniqueIndex('threads_client_id_user_id_unique').on(t.clientId, t.userId),
|
65
|
+
}),
|
66
|
+
);
|
60
67
|
|
61
68
|
export type NewThread = typeof threads.$inferInsert;
|
62
69
|
export type ThreadItem = typeof threads.$inferSelect;
|