@lobehub/lobehub 2.0.0-next.12 → 2.0.0-next.14
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 +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/const/src/version.ts +3 -3
- package/packages/database/src/repositories/dataImporter/deprecated/__tests__/index.test.ts +2 -1
- package/packages/database/src/repositories/dataImporter/deprecated/index.ts +7 -1
- package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +9 -0
- package/src/app/[variants]/(main)/(mobile)/me/(home)/layout.tsx +0 -2
- package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/Actions.tsx +3 -28
- package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +0 -2
- package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +1 -5
- package/src/app/[variants]/(main)/chat/settings/features/HeaderContent.tsx +2 -62
- package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +1 -1
- package/src/app/[variants]/(main)/image/page.tsx +0 -2
- package/src/app/[variants]/(main)/profile/_layout/Desktop/index.tsx +23 -24
- package/src/app/[variants]/(main)/profile/_layout/Mobile/index.tsx +5 -9
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +0 -2
- package/src/app/[variants]/(main)/settings/_layout/Mobile/index.tsx +0 -2
- package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +1 -1
- package/src/app/[variants]/loading/index.tsx +1 -10
- package/src/components/Link.tsx +12 -0
- package/src/envs/app.ts +5 -8
- package/src/features/DataImporter/index.tsx +15 -60
- package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -2
- package/src/hooks/useInterceptingRoutes.test.ts +21 -3
- package/src/libs/trpc/client/index.ts +0 -1
- package/src/libs/trpc/client/lambda.ts +8 -5
- package/src/libs/trpc/lambda/context.ts +4 -1
- package/src/server/routers/desktop/mcp.ts +1 -3
- package/src/server/routers/lambda/config/index.test.ts +2 -2
- package/src/server/routers/tools/mcp.ts +2 -3
- package/src/server/routers/tools/search.test.ts +1 -7
- package/src/server/routers/tools/search.ts +1 -4
- package/src/services/__tests__/tool.test.ts +0 -3
- package/src/services/aiModel/index.test.ts +0 -3
- package/src/services/aiModel/index.ts +1 -7
- package/src/services/aiProvider/index.test.ts +0 -3
- package/src/services/aiProvider/index.ts +1 -7
- package/src/services/chatGroup/index.ts +1 -10
- package/src/services/config.ts +1 -65
- package/src/services/export/index.ts +1 -4
- package/src/services/file/index.ts +1 -11
- package/src/services/import/index.ts +1 -7
- package/src/services/message/index.ts +1 -11
- package/src/services/plugin/index.ts +1 -11
- package/src/services/session/index.ts +1 -11
- package/src/services/tableViewer/client.ts +12 -15
- package/src/services/thread/index.ts +1 -7
- package/src/services/topic/index.ts +1 -11
- package/src/services/user/index.ts +1 -13
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -241
- package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +26 -1
- package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +3 -1
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +1 -138
- package/src/store/user/slices/common/action.test.ts +1 -4
- package/src/app/(backend)/trpc/edge/[trpc]/route.ts +0 -26
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +0 -48
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Header.tsx +0 -33
- package/src/app/[variants]/(main)/(mobile)/me/data/layout.tsx +0 -13
- package/src/app/[variants]/(main)/(mobile)/me/data/loading.tsx +0 -5
- package/src/app/[variants]/(main)/(mobile)/me/data/page.tsx +0 -29
- package/src/app/[variants]/(main)/chat/features/Migration/DBReader.ts +0 -290
- package/src/app/[variants]/(main)/chat/features/Migration/ExportConfigButton.tsx +0 -35
- package/src/app/[variants]/(main)/chat/features/Migration/Failed.tsx +0 -120
- package/src/app/[variants]/(main)/chat/features/Migration/Modal.tsx +0 -81
- package/src/app/[variants]/(main)/chat/features/Migration/Start.tsx +0 -108
- package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +0 -71
- package/src/app/[variants]/(main)/chat/features/Migration/const.ts +0 -15
- package/src/app/[variants]/(main)/chat/features/Migration/index.tsx +0 -50
- package/src/app/[variants]/loading/Client/Content.tsx +0 -48
- package/src/app/[variants]/loading/Client/Error.tsx +0 -27
- package/src/app/[variants]/loading/Client/Redirect.tsx +0 -47
- package/src/app/[variants]/loading/Client/index.tsx +0 -22
- package/src/components/InnerLink.tsx +0 -20
- package/src/database/_deprecated/core/__tests__/db-upgrade.test.ts +0 -42
- package/src/database/_deprecated/core/__tests__/db.test.ts +0 -79
- package/src/database/_deprecated/core/__tests__/model.test.ts +0 -55
- package/src/database/_deprecated/core/db.ts +0 -246
- package/src/database/_deprecated/core/index.ts +0 -2
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/input.json +0 -55
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/output.json +0 -60
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.test.ts +0 -14
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.ts +0 -22
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +0 -105
- package/src/database/_deprecated/core/model.ts +0 -218
- package/src/database/_deprecated/core/schemas.ts +0 -88
- package/src/database/_deprecated/core/types/db.ts +0 -15
- package/src/database/_deprecated/models/__DEBUG.ts +0 -124
- package/src/database/_deprecated/models/__tests__/file.test.ts +0 -83
- package/src/database/_deprecated/models/__tests__/message.test.ts +0 -426
- package/src/database/_deprecated/models/__tests__/plugin.test.ts +0 -81
- package/src/database/_deprecated/models/__tests__/session.test.ts +0 -253
- package/src/database/_deprecated/models/__tests__/sessionGroup.test.ts +0 -220
- package/src/database/_deprecated/models/__tests__/topic.test.ts +0 -523
- package/src/database/_deprecated/models/__tests__/user.test.ts +0 -82
- package/src/database/_deprecated/models/file.ts +0 -51
- package/src/database/_deprecated/models/message.ts +0 -277
- package/src/database/_deprecated/models/plugin.ts +0 -62
- package/src/database/_deprecated/models/session.ts +0 -271
- package/src/database/_deprecated/models/sessionGroup.ts +0 -93
- package/src/database/_deprecated/models/topic.ts +0 -250
- package/src/database/_deprecated/models/user.ts +0 -69
- package/src/database/_deprecated/schemas/files.ts +0 -39
- package/src/database/_deprecated/schemas/message.ts +0 -50
- package/src/database/_deprecated/schemas/plugin.ts +0 -12
- package/src/database/_deprecated/schemas/session.ts +0 -54
- package/src/database/_deprecated/schemas/sessionGroup.ts +0 -8
- package/src/database/_deprecated/schemas/topic.ts +0 -12
- package/src/database/_deprecated/schemas/user.ts +0 -40
- package/src/features/DataImporter/_deprecated.ts +0 -43
- package/src/features/InitClientDB/EnableModal.tsx +0 -118
- package/src/features/InitClientDB/ErrorResult.tsx +0 -143
- package/src/features/InitClientDB/InitIndicator.tsx +0 -124
- package/src/features/InitClientDB/PGliteIcon.tsx +0 -28
- package/src/features/InitClientDB/features/DatabaseRepair/Backup.tsx +0 -75
- package/src/features/InitClientDB/features/DatabaseRepair/Diagnosis.tsx +0 -98
- package/src/features/InitClientDB/features/DatabaseRepair/Repair.tsx +0 -218
- package/src/features/InitClientDB/features/DatabaseRepair/index.tsx +0 -91
- package/src/features/InitClientDB/index.tsx +0 -37
- package/src/libs/trpc/client/edge.ts +0 -26
- package/src/libs/trpc/edge/context.ts +0 -71
- package/src/libs/trpc/edge/index.ts +0 -45
- package/src/libs/trpc/edge/init.ts +0 -26
- package/src/libs/trpc/edge/middleware/jwtPayload.test.ts +0 -75
- package/src/libs/trpc/edge/middleware/jwtPayload.ts +0 -14
- package/src/migrations/FromV0ToV1.ts +0 -10
- package/src/migrations/FromV1ToV2/fixtures/input-v1-session.json +0 -191
- package/src/migrations/FromV1ToV2/fixtures/output-v2.json +0 -202
- package/src/migrations/FromV1ToV2/index.ts +0 -82
- package/src/migrations/FromV1ToV2/migrations.test.ts +0 -224
- package/src/migrations/FromV1ToV2/types/v1.ts +0 -78
- package/src/migrations/FromV1ToV2/types/v2.ts +0 -52
- package/src/migrations/FromV2ToV3/fixtures/input-v2-session.json +0 -72
- package/src/migrations/FromV2ToV3/fixtures/output-v3-from-v1.json +0 -203
- package/src/migrations/FromV2ToV3/fixtures/output-v3.json +0 -74
- package/src/migrations/FromV2ToV3/index.ts +0 -30
- package/src/migrations/FromV2ToV3/migrations.test.ts +0 -42
- package/src/migrations/FromV2ToV3/types/v3.ts +0 -27
- package/src/migrations/FromV3ToV4/fixtures/azure-input-v3.json +0 -79
- package/src/migrations/FromV3ToV4/fixtures/azure-output-v4.json +0 -75
- package/src/migrations/FromV3ToV4/fixtures/ollama-input-v3.json +0 -85
- package/src/migrations/FromV3ToV4/fixtures/ollama-output-v4.json +0 -86
- package/src/migrations/FromV3ToV4/fixtures/openai-input-v3.json +0 -77
- package/src/migrations/FromV3ToV4/fixtures/openai-output-v4.json +0 -77
- package/src/migrations/FromV3ToV4/fixtures/openrouter-input-v3.json +0 -82
- package/src/migrations/FromV3ToV4/fixtures/openrouter-output-v4.json +0 -85
- package/src/migrations/FromV3ToV4/fixtures/output-v4-from-v1.json +0 -203
- package/src/migrations/FromV3ToV4/index.ts +0 -102
- package/src/migrations/FromV3ToV4/migrations.test.ts +0 -195
- package/src/migrations/FromV3ToV4/types/v3.ts +0 -52
- package/src/migrations/FromV3ToV4/types/v4.ts +0 -37
- package/src/migrations/FromV4ToV5/fixtures/from-v1-to-v5-output.json +0 -245
- package/src/migrations/FromV4ToV5/fixtures/function-input-v4.json +0 -96
- package/src/migrations/FromV4ToV5/fixtures/function-output-v5.json +0 -120
- package/src/migrations/FromV4ToV5/index.ts +0 -58
- package/src/migrations/FromV4ToV5/migrations.test.ts +0 -49
- package/src/migrations/FromV4ToV5/types/v4.ts +0 -21
- package/src/migrations/FromV4ToV5/types/v5.ts +0 -27
- package/src/migrations/FromV5ToV6/fixtures/from-v1-to-v6-output.json +0 -247
- package/src/migrations/FromV5ToV6/fixtures/session-input-v5.json +0 -81
- package/src/migrations/FromV5ToV6/fixtures/session-output-v6.json +0 -85
- package/src/migrations/FromV5ToV6/index.ts +0 -61
- package/src/migrations/FromV5ToV6/migrations.test.ts +0 -50
- package/src/migrations/FromV5ToV6/types/v5.ts +0 -48
- package/src/migrations/FromV5ToV6/types/v6.ts +0 -63
- package/src/migrations/FromV6ToV7/fixtures/output-v7-from-v1.json +0 -203
- package/src/migrations/FromV6ToV7/fixtures/provider-input-v6.json +0 -103
- package/src/migrations/FromV6ToV7/fixtures/provider-output-v7.json +0 -118
- package/src/migrations/FromV6ToV7/index.ts +0 -101
- package/src/migrations/FromV6ToV7/migrations.test.ts +0 -64
- package/src/migrations/FromV6ToV7/types/v6.ts +0 -61
- package/src/migrations/FromV6ToV7/types/v7.ts +0 -69
- package/src/migrations/VersionController.test.ts +0 -88
- package/src/migrations/VersionController.ts +0 -67
- package/src/migrations/index.ts +0 -61
- package/src/server/routers/edge/appStatus.ts +0 -3
- package/src/server/routers/edge/index.ts +0 -14
- package/src/server/routers/edge/upload.ts +0 -16
- package/src/services/aiModel/client.ts +0 -70
- package/src/services/aiProvider/client.ts +0 -58
- package/src/services/baseClientService/index.ts +0 -9
- package/src/services/chatGroup/client.ts +0 -63
- package/src/services/export/_deprecated.ts +0 -155
- package/src/services/export/client.ts +0 -15
- package/src/services/file/_deprecated.test.ts +0 -119
- package/src/services/file/_deprecated.ts +0 -80
- package/src/services/file/client.test.ts +0 -199
- package/src/services/file/client.ts +0 -85
- package/src/services/import/_deprecated.ts +0 -115
- package/src/services/import/client.test.ts +0 -1015
- package/src/services/import/client.ts +0 -64
- package/src/services/message/_deprecated.test.ts +0 -398
- package/src/services/message/_deprecated.ts +0 -168
- package/src/services/message/client.test.ts +0 -410
- package/src/services/message/client.ts +0 -192
- package/src/services/plugin/_deprecated.test.ts +0 -162
- package/src/services/plugin/_deprecated.ts +0 -42
- package/src/services/plugin/client.test.ts +0 -177
- package/src/services/plugin/client.ts +0 -46
- package/src/services/session/_deprecated.test.ts +0 -440
- package/src/services/session/_deprecated.ts +0 -190
- package/src/services/session/client.test.ts +0 -413
- package/src/services/session/client.ts +0 -193
- package/src/services/thread/client.ts +0 -51
- package/src/services/topic/_deprecated.test.ts +0 -245
- package/src/services/topic/_deprecated.ts +0 -75
- package/src/services/topic/client.ts +0 -89
- package/src/services/topic/pglite.test.ts +0 -212
- package/src/services/user/_deprecated.test.ts +0 -101
- package/src/services/user/_deprecated.ts +0 -70
- package/src/services/user/client.test.ts +0 -111
- package/src/services/user/client.ts +0 -104
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Alert, Button, CodeEditor, Icon, Text } from '@lobehub/ui';
|
|
4
|
-
import { Card, List } from 'antd';
|
|
5
|
-
import { createStyles } from 'antd-style';
|
|
6
|
-
import dayjs from 'dayjs';
|
|
7
|
-
import isEqual from 'fast-deep-equal';
|
|
8
|
-
import { AlertCircle, CheckCircle, Play } from 'lucide-react';
|
|
9
|
-
import { memo, useState } from 'react';
|
|
10
|
-
import { useTranslation } from 'react-i18next';
|
|
11
|
-
import { Flexbox } from 'react-layout-kit';
|
|
12
|
-
|
|
13
|
-
import { clientDB, updateMigrationRecord } from '@/database/client/db';
|
|
14
|
-
import { useGlobalStore } from '@/store/global';
|
|
15
|
-
import { clientDBSelectors } from '@/store/global/selectors';
|
|
16
|
-
|
|
17
|
-
// 使用 antd-style 创建样式
|
|
18
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
19
|
-
actionBar: css`
|
|
20
|
-
display: flex;
|
|
21
|
-
justify-content: flex-end;
|
|
22
|
-
margin-block-start: ${token.marginSM}px;
|
|
23
|
-
`,
|
|
24
|
-
card: css`
|
|
25
|
-
margin-block-end: ${token.marginMD}px;
|
|
26
|
-
border-radius: ${token.borderRadiusLG}px;
|
|
27
|
-
`,
|
|
28
|
-
codeBlock: css`
|
|
29
|
-
overflow-x: auto;
|
|
30
|
-
|
|
31
|
-
margin-block: ${token.marginSM}px;
|
|
32
|
-
margin-inline: 0;
|
|
33
|
-
padding: ${token.paddingSM}px;
|
|
34
|
-
border-radius: ${token.borderRadiusSM}px;
|
|
35
|
-
|
|
36
|
-
font-family: ${token.fontFamilyCode};
|
|
37
|
-
font-size: 12px;
|
|
38
|
-
|
|
39
|
-
background: ${token.colorBgTextHover};
|
|
40
|
-
`,
|
|
41
|
-
container: css`
|
|
42
|
-
overflow-y: auto;
|
|
43
|
-
padding: 0;
|
|
44
|
-
`,
|
|
45
|
-
header: css`
|
|
46
|
-
display: flex;
|
|
47
|
-
align-items: center;
|
|
48
|
-
margin-block-end: ${token.marginMD}px;
|
|
49
|
-
`,
|
|
50
|
-
migrationItem: css`
|
|
51
|
-
display: flex;
|
|
52
|
-
align-items: center;
|
|
53
|
-
justify-content: space-between;
|
|
54
|
-
|
|
55
|
-
padding-block: ${token.paddingSM}px;
|
|
56
|
-
padding-inline: 0;
|
|
57
|
-
border-block-end: none;
|
|
58
|
-
`,
|
|
59
|
-
spotlight: css`
|
|
60
|
-
margin-block-end: ${token.marginLG}px;
|
|
61
|
-
`,
|
|
62
|
-
|
|
63
|
-
templateCard: css`
|
|
64
|
-
margin-block-end: ${token.marginSM}px;
|
|
65
|
-
`,
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
|
-
interface QueryResult {
|
|
69
|
-
message: string;
|
|
70
|
-
success: boolean;
|
|
71
|
-
}
|
|
72
|
-
const Repair = memo(() => {
|
|
73
|
-
const { t } = useTranslation('common');
|
|
74
|
-
|
|
75
|
-
const { styles } = useStyles();
|
|
76
|
-
const [sqlQuery, setSqlQuery] = useState('');
|
|
77
|
-
const [queryResult, setQueryResult] = useState<QueryResult | null>(null);
|
|
78
|
-
const [showSQLHash, setShowSQLHash] = useState('');
|
|
79
|
-
|
|
80
|
-
const errorMigrations = useGlobalStore(clientDBSelectors.errorMigrations, isEqual);
|
|
81
|
-
|
|
82
|
-
const handleExecuteSQL = async () => {
|
|
83
|
-
try {
|
|
84
|
-
// 移除 BEGIN 和 COMMIT
|
|
85
|
-
let processedSQL = sqlQuery.replaceAll(/BEGIN;|COMMIT;/g, '');
|
|
86
|
-
|
|
87
|
-
// 分割 SQL 语句(使用 statement-breakpoint 作为分隔符)
|
|
88
|
-
const migrationQueries = processedSQL.split('--> statement-breakpoint');
|
|
89
|
-
|
|
90
|
-
// 手动管理事务
|
|
91
|
-
await clientDB.execute('BEGIN;');
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
for (const query of migrationQueries) {
|
|
95
|
-
if (query.trim()) {
|
|
96
|
-
await clientDB.execute(query);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
await clientDB.execute('COMMIT;');
|
|
100
|
-
|
|
101
|
-
setQueryResult({
|
|
102
|
-
message: `SQL executed successfully.`,
|
|
103
|
-
success: true,
|
|
104
|
-
});
|
|
105
|
-
} catch (error) {
|
|
106
|
-
await clientDB.execute('ROLLBACK;');
|
|
107
|
-
|
|
108
|
-
throw error;
|
|
109
|
-
}
|
|
110
|
-
} catch (error) {
|
|
111
|
-
setQueryResult({ message: (error as Error).message, success: false });
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
<div>
|
|
117
|
-
<Card
|
|
118
|
-
className={styles.card}
|
|
119
|
-
extra={<Text type="secondary">{t('clientDB.solve.repair.desc')}</Text>}
|
|
120
|
-
title={t('clientDB.solve.repair.title')}
|
|
121
|
-
variant={'borderless'}
|
|
122
|
-
>
|
|
123
|
-
<List
|
|
124
|
-
dataSource={errorMigrations}
|
|
125
|
-
renderItem={(migration) => (
|
|
126
|
-
<>
|
|
127
|
-
<List.Item
|
|
128
|
-
actions={[
|
|
129
|
-
<Button
|
|
130
|
-
icon={<Icon icon={Play} />}
|
|
131
|
-
key="retry"
|
|
132
|
-
onClick={() => {
|
|
133
|
-
setShowSQLHash(!!showSQLHash ? '' : migration.hash);
|
|
134
|
-
setSqlQuery(migration.sql.join('--> statement-breakpoint\n'));
|
|
135
|
-
}}
|
|
136
|
-
>
|
|
137
|
-
{t('clientDB.solve.repair.runSQL')}
|
|
138
|
-
</Button>,
|
|
139
|
-
]}
|
|
140
|
-
className={styles.migrationItem}
|
|
141
|
-
key={migration.hash}
|
|
142
|
-
>
|
|
143
|
-
<List.Item.Meta
|
|
144
|
-
description={
|
|
145
|
-
<Flexbox>
|
|
146
|
-
{t('clientDB.solve.diagnosis.createdAt')}
|
|
147
|
-
{dayjs(migration.folderMillis).format('YYYY-MM-DD hh:mm:ss')} ·
|
|
148
|
-
</Flexbox>
|
|
149
|
-
}
|
|
150
|
-
title={migration.sql[0]}
|
|
151
|
-
/>
|
|
152
|
-
</List.Item>
|
|
153
|
-
{showSQLHash === migration.hash && (
|
|
154
|
-
<Card
|
|
155
|
-
className={styles.card}
|
|
156
|
-
extra={<Text type="secondary">{t('clientDB.solve.repair.sql.desc')}</Text>}
|
|
157
|
-
title={t('clientDB.solve.repair.sql.title')}
|
|
158
|
-
>
|
|
159
|
-
<Flexbox gap={16}>
|
|
160
|
-
<CodeEditor
|
|
161
|
-
language={'sql'}
|
|
162
|
-
onValueChange={(e) => setSqlQuery(e)}
|
|
163
|
-
placeholder={t('clientDB.solve.repair.sql.placeholder')}
|
|
164
|
-
style={{ fontFamily: 'monospace', height: 300 }}
|
|
165
|
-
value={sqlQuery}
|
|
166
|
-
/>
|
|
167
|
-
<Flexbox horizontal style={{ justifyContent: 'space-between' }}>
|
|
168
|
-
<Button onClick={() => setSqlQuery('')}>
|
|
169
|
-
{t('clientDB.solve.repair.sql.clear')}
|
|
170
|
-
</Button>
|
|
171
|
-
<Button disabled={!sqlQuery.trim()} onClick={handleExecuteSQL} type="primary">
|
|
172
|
-
{t('clientDB.solve.repair.sql.run')}
|
|
173
|
-
</Button>
|
|
174
|
-
</Flexbox>
|
|
175
|
-
|
|
176
|
-
{queryResult && (
|
|
177
|
-
<Alert
|
|
178
|
-
action={
|
|
179
|
-
queryResult.success && (
|
|
180
|
-
<Button
|
|
181
|
-
key="complete"
|
|
182
|
-
onClick={() => updateMigrationRecord(migration.hash)}
|
|
183
|
-
size={'small'}
|
|
184
|
-
type="primary"
|
|
185
|
-
>
|
|
186
|
-
{t('clientDB.solve.repair.sql.markFinished')}
|
|
187
|
-
</Button>
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
|
-
description={
|
|
191
|
-
<pre style={{ marginTop: '8px', whiteSpace: 'pre-wrap' }}>
|
|
192
|
-
{queryResult.message}
|
|
193
|
-
</pre>
|
|
194
|
-
}
|
|
195
|
-
icon={
|
|
196
|
-
queryResult.success ? (
|
|
197
|
-
<AlertCircle size={16} />
|
|
198
|
-
) : (
|
|
199
|
-
<CheckCircle size={16} />
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
message={t('clientDB.solve.repair.sql.result')}
|
|
203
|
-
showIcon
|
|
204
|
-
type={queryResult.success ? 'success' : 'error'}
|
|
205
|
-
/>
|
|
206
|
-
)}
|
|
207
|
-
</Flexbox>
|
|
208
|
-
</Card>
|
|
209
|
-
)}
|
|
210
|
-
</>
|
|
211
|
-
)}
|
|
212
|
-
/>
|
|
213
|
-
</Card>
|
|
214
|
-
</div>
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
export default Repair;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Button, Segmented } from '@lobehub/ui';
|
|
4
|
-
import { createStyles } from 'antd-style';
|
|
5
|
-
import { AlertCircle, ArrowLeft, PenToolIcon as Tool } from 'lucide-react';
|
|
6
|
-
import { memo, useState } from 'react';
|
|
7
|
-
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import { Flexbox } from 'react-layout-kit';
|
|
9
|
-
|
|
10
|
-
import Backup from './Backup';
|
|
11
|
-
import Diagnosis from './Diagnosis';
|
|
12
|
-
import Repair from './Repair';
|
|
13
|
-
|
|
14
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
15
|
-
backButton: css`
|
|
16
|
-
margin-inline-end: ${token.marginSM}px;
|
|
17
|
-
padding-block: 4px;
|
|
18
|
-
padding-inline: 8px;
|
|
19
|
-
`,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
enum DatabaseRepairTab {
|
|
23
|
-
Backup = 'backup',
|
|
24
|
-
Diagnosis = 'diagnosis',
|
|
25
|
-
Repair = 'repair',
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface DatabaseRepairProps {
|
|
29
|
-
setShowRepair: (value: boolean) => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const DatabaseRepair = memo<DatabaseRepairProps>(({ setShowRepair }) => {
|
|
33
|
-
const { t } = useTranslation('common');
|
|
34
|
-
const { styles } = useStyles();
|
|
35
|
-
const [activeTab, setActiveTab] = useState<DatabaseRepairTab>(DatabaseRepairTab.Diagnosis);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<Flexbox gap={12}>
|
|
39
|
-
<Flexbox horizontal justify={'space-between'}>
|
|
40
|
-
<Button
|
|
41
|
-
className={styles.backButton}
|
|
42
|
-
icon={<ArrowLeft size={16} />}
|
|
43
|
-
onClick={() => setShowRepair(false)}
|
|
44
|
-
type="text"
|
|
45
|
-
>
|
|
46
|
-
{t('back')}
|
|
47
|
-
</Button>
|
|
48
|
-
<Segmented
|
|
49
|
-
onChange={(v) => setActiveTab(v as DatabaseRepairTab)}
|
|
50
|
-
options={[
|
|
51
|
-
{
|
|
52
|
-
label: (
|
|
53
|
-
<Flexbox align={'center'} horizontal>
|
|
54
|
-
<AlertCircle size={16} style={{ marginRight: 8 }} />
|
|
55
|
-
{t('clientDB.solve.tabs.diagnosis')}
|
|
56
|
-
</Flexbox>
|
|
57
|
-
),
|
|
58
|
-
value: 'diagnosis',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
label: (
|
|
62
|
-
<Flexbox align={'center'} horizontal>
|
|
63
|
-
<Tool size={16} style={{ marginRight: 8 }} />
|
|
64
|
-
{t('clientDB.solve.tabs.repair')}
|
|
65
|
-
</Flexbox>
|
|
66
|
-
),
|
|
67
|
-
value: 'repair',
|
|
68
|
-
},
|
|
69
|
-
// {
|
|
70
|
-
// label: (
|
|
71
|
-
// <Flexbox align={'center'} horizontal>
|
|
72
|
-
// <Shield size={16} style={{ marginRight: 8 }} />
|
|
73
|
-
// {t('clientDB.solve.tabs.backup')}
|
|
74
|
-
// </Flexbox>
|
|
75
|
-
// ),
|
|
76
|
-
// value: 'backup',
|
|
77
|
-
// },
|
|
78
|
-
]}
|
|
79
|
-
value={activeTab}
|
|
80
|
-
/>
|
|
81
|
-
<Flexbox width={36} />
|
|
82
|
-
</Flexbox>
|
|
83
|
-
|
|
84
|
-
{activeTab === DatabaseRepairTab.Diagnosis && <Diagnosis />}
|
|
85
|
-
{activeTab === DatabaseRepairTab.Repair && <Repair />}
|
|
86
|
-
{activeTab === DatabaseRepairTab.Backup && <Backup />}
|
|
87
|
-
</Flexbox>
|
|
88
|
-
);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
export default DatabaseRepair;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Spin } from 'antd';
|
|
4
|
-
import dynamic from 'next/dynamic';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
|
|
7
|
-
import { useGlobalStore } from '@/store/global';
|
|
8
|
-
import { systemStatusSelectors } from '@/store/global/selectors';
|
|
9
|
-
|
|
10
|
-
const Modal = dynamic(() => import('./EnableModal'), {
|
|
11
|
-
loading: () => <Spin fullscreen />,
|
|
12
|
-
ssr: false,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const InitIndicator = dynamic(() => import('./InitIndicator'), {
|
|
16
|
-
ssr: false,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
interface InitClientDBProps {
|
|
20
|
-
bottom?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const InitClientDB = memo<InitClientDBProps>(({ bottom }) => {
|
|
24
|
-
const isPgliteNotEnabled = useGlobalStore(systemStatusSelectors.isPgliteNotEnabled);
|
|
25
|
-
const isPgliteNotInited = useGlobalStore(systemStatusSelectors.isPgliteNotInited);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<>
|
|
29
|
-
{/* 当用户没有设置启用 pglite 时,强弹窗引导用户来开启弹窗 */}
|
|
30
|
-
{isPgliteNotEnabled && <Modal open={isPgliteNotEnabled} />}
|
|
31
|
-
{/* 当用户已经启用 pglite 但没有初始化时,展示初始化指示器 */}
|
|
32
|
-
{isPgliteNotInited && <InitIndicator bottom={bottom} show={isPgliteNotInited} />}
|
|
33
|
-
</>
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
export default InitClientDB;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
|
2
|
-
import superjson from 'superjson';
|
|
3
|
-
|
|
4
|
-
import { isDesktop } from '@/const/version';
|
|
5
|
-
import type { EdgeRouter } from '@/server/routers/edge';
|
|
6
|
-
import { fetchWithDesktopRemoteRPC } from '@/utils/electron/desktopRemoteRPCFetch';
|
|
7
|
-
|
|
8
|
-
export const edgeClient = createTRPCClient<EdgeRouter>({
|
|
9
|
-
links: [
|
|
10
|
-
httpBatchLink({
|
|
11
|
-
fetch: isDesktop
|
|
12
|
-
? // eslint-disable-next-line no-undef
|
|
13
|
-
(input, init) => fetchWithDesktopRemoteRPC(input as string, init as RequestInit)
|
|
14
|
-
: undefined,
|
|
15
|
-
headers: async () => {
|
|
16
|
-
// dynamic import to avoid circular dependency
|
|
17
|
-
const { createHeaderWithAuth } = await import('@/services/_auth');
|
|
18
|
-
|
|
19
|
-
return createHeaderWithAuth();
|
|
20
|
-
},
|
|
21
|
-
maxURLLength: 2083,
|
|
22
|
-
transformer: superjson,
|
|
23
|
-
url: '/trpc/edge',
|
|
24
|
-
}),
|
|
25
|
-
],
|
|
26
|
-
});
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { ClientSecretPayload } from '@lobechat/types';
|
|
2
|
-
import { User } from 'next-auth';
|
|
3
|
-
import { NextRequest } from 'next/server';
|
|
4
|
-
|
|
5
|
-
import { LOBE_CHAT_AUTH_HEADER, enableClerk, enableNextAuth } from '@/const/auth';
|
|
6
|
-
import { ClerkAuth, IClerkAuth } from '@/libs/clerk-auth';
|
|
7
|
-
|
|
8
|
-
export interface AuthContext {
|
|
9
|
-
authorizationHeader?: string | null;
|
|
10
|
-
clerkAuth?: IClerkAuth;
|
|
11
|
-
jwtPayload?: ClientSecretPayload | null;
|
|
12
|
-
nextAuth?: User;
|
|
13
|
-
userId?: string | null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Inner function for `createContext` where we create the context.
|
|
18
|
-
* This is useful for testing when we don't want to mock Next.js' request/response
|
|
19
|
-
*/
|
|
20
|
-
export const createContextInner = async (params?: {
|
|
21
|
-
authorizationHeader?: string | null;
|
|
22
|
-
clerkAuth?: IClerkAuth;
|
|
23
|
-
nextAuth?: User;
|
|
24
|
-
userId?: string | null;
|
|
25
|
-
}): Promise<AuthContext> => ({
|
|
26
|
-
authorizationHeader: params?.authorizationHeader,
|
|
27
|
-
clerkAuth: params?.clerkAuth,
|
|
28
|
-
nextAuth: params?.nextAuth,
|
|
29
|
-
userId: params?.userId,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export type EdgeContext = Awaited<ReturnType<typeof createContextInner>>;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Creates context for an incoming request
|
|
36
|
-
* @link https://trpc.io/docs/v11/context
|
|
37
|
-
*/
|
|
38
|
-
export const createEdgeContext = async (request: NextRequest): Promise<EdgeContext> => {
|
|
39
|
-
// for API-response caching see https://trpc.io/docs/v11/caching
|
|
40
|
-
|
|
41
|
-
const authorization = request.headers.get(LOBE_CHAT_AUTH_HEADER);
|
|
42
|
-
|
|
43
|
-
let userId;
|
|
44
|
-
let auth;
|
|
45
|
-
|
|
46
|
-
if (enableClerk) {
|
|
47
|
-
const clerkAuth = new ClerkAuth();
|
|
48
|
-
const result = clerkAuth.getAuthFromRequest(request);
|
|
49
|
-
auth = result.clerkAuth;
|
|
50
|
-
userId = result.userId;
|
|
51
|
-
|
|
52
|
-
return createContextInner({ authorizationHeader: authorization, clerkAuth: auth, userId });
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (enableNextAuth) {
|
|
56
|
-
try {
|
|
57
|
-
const { default: NextAuth } = await import('@/libs/next-auth');
|
|
58
|
-
|
|
59
|
-
const session = await NextAuth.auth();
|
|
60
|
-
if (session && session?.user?.id) {
|
|
61
|
-
auth = session.user;
|
|
62
|
-
userId = session.user.id;
|
|
63
|
-
}
|
|
64
|
-
return createContextInner({ authorizationHeader: authorization, nextAuth: auth, userId });
|
|
65
|
-
} catch (e) {
|
|
66
|
-
console.error('next auth err', e);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return createContextInner({ authorizationHeader: authorization, userId });
|
|
71
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is your entry point to setup the root configuration for tRPC on the server.
|
|
3
|
-
* - `initTRPC` should only be used once per app.
|
|
4
|
-
* - We export only the functionality that we use so we can enforce which base procedures should be used
|
|
5
|
-
*
|
|
6
|
-
* Learn how to create protected base procedures and other things below:
|
|
7
|
-
* @link https://trpc.io/docs/v11/router
|
|
8
|
-
* @link https://trpc.io/docs/v11/procedures
|
|
9
|
-
*/
|
|
10
|
-
import { DESKTOP_USER_ID } from '@/const/desktop';
|
|
11
|
-
import { isDesktop } from '@/const/version';
|
|
12
|
-
|
|
13
|
-
import { edgeTrpc } from './init';
|
|
14
|
-
import { jwtPayloadChecker } from './middleware/jwtPayload';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Create a router
|
|
18
|
-
* @link https://trpc.io/docs/v11/router
|
|
19
|
-
*/
|
|
20
|
-
export const router = edgeTrpc.router;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Create an unprotected procedure
|
|
24
|
-
* @link https://trpc.io/docs/v11/procedures
|
|
25
|
-
**/
|
|
26
|
-
export const publicProcedure = edgeTrpc.procedure.use(({ next, ctx }) => {
|
|
27
|
-
return next({
|
|
28
|
-
ctx: { userId: isDesktop ? DESKTOP_USER_ID : ctx.userId },
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// procedure that asserts that the user add the password
|
|
33
|
-
export const passwordProcedure = edgeTrpc.procedure.use(jwtPayloadChecker);
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Merge multiple routers together
|
|
37
|
-
* @link https://trpc.io/docs/v11/merging-routers
|
|
38
|
-
*/
|
|
39
|
-
export const mergeRouters = edgeTrpc.mergeRouters;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Create a server-side caller
|
|
43
|
-
* @link https://trpc.io/docs/v11/server/server-side-calls
|
|
44
|
-
*/
|
|
45
|
-
export const createCallerFactory = edgeTrpc.createCallerFactory;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is your entry point to setup the root configuration for tRPC on the server.
|
|
3
|
-
* - `initTRPC` should only be used once per app.
|
|
4
|
-
* - We export only the functionality that we use so we can enforce which base procedures should be used
|
|
5
|
-
*
|
|
6
|
-
* Learn how to create protected base procedures and other things below:
|
|
7
|
-
* @link https://trpc.io/docs/v11/router
|
|
8
|
-
* @link https://trpc.io/docs/v11/procedures
|
|
9
|
-
*/
|
|
10
|
-
import { initTRPC } from '@trpc/server';
|
|
11
|
-
import superjson from 'superjson';
|
|
12
|
-
|
|
13
|
-
import type { EdgeContext } from './context';
|
|
14
|
-
|
|
15
|
-
export const edgeTrpc = initTRPC.context<EdgeContext>().create({
|
|
16
|
-
/**
|
|
17
|
-
* @link https://trpc.io/docs/v11/error-formatting
|
|
18
|
-
*/
|
|
19
|
-
errorFormatter({ shape }) {
|
|
20
|
-
return shape;
|
|
21
|
-
},
|
|
22
|
-
/**
|
|
23
|
-
* @link https://trpc.io/docs/v11/data-transformers
|
|
24
|
-
*/
|
|
25
|
-
transformer: superjson,
|
|
26
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// @vitest-environment node
|
|
2
|
-
import * as utils from '@lobechat/utils/server';
|
|
3
|
-
import { TRPCError } from '@trpc/server';
|
|
4
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
-
|
|
6
|
-
import { createCallerFactory } from '@/libs/trpc/edge';
|
|
7
|
-
import { AuthContext, createContextInner } from '@/libs/trpc/edge/context';
|
|
8
|
-
import { edgeTrpc as trpc } from '@/libs/trpc/edge/init';
|
|
9
|
-
|
|
10
|
-
import { jwtPayloadChecker } from './jwtPayload';
|
|
11
|
-
|
|
12
|
-
const appRouter = trpc.router({
|
|
13
|
-
protectedQuery: trpc.procedure.use(jwtPayloadChecker).query(async ({ ctx }) => {
|
|
14
|
-
return ctx.jwtPayload;
|
|
15
|
-
}),
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const createCaller = createCallerFactory(appRouter);
|
|
19
|
-
let ctx: AuthContext;
|
|
20
|
-
let router: ReturnType<typeof createCaller>;
|
|
21
|
-
|
|
22
|
-
vi.mock('@/libs/next-auth/edge', () => {
|
|
23
|
-
return {
|
|
24
|
-
auth: vi.fn().mockResolvedValue(undefined),
|
|
25
|
-
};
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
vi.resetAllMocks();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('passwordChecker middleware', () => {
|
|
33
|
-
it('should throw UNAUTHORIZED error if authorizationHeader is not present in context', async () => {
|
|
34
|
-
ctx = await createContextInner();
|
|
35
|
-
router = createCaller(ctx);
|
|
36
|
-
|
|
37
|
-
await expect(router.protectedQuery()).rejects.toThrow(new TRPCError({ code: 'UNAUTHORIZED' }));
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should call next with jwtPayload in context if access code is correct', async () => {
|
|
41
|
-
const jwtPayload = { accessCode: '123' };
|
|
42
|
-
|
|
43
|
-
vi.spyOn(utils, 'getXorPayload').mockResolvedValue(jwtPayload);
|
|
44
|
-
|
|
45
|
-
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
46
|
-
router = createCaller(ctx);
|
|
47
|
-
|
|
48
|
-
const data = await router.protectedQuery();
|
|
49
|
-
|
|
50
|
-
expect(data).toEqual(jwtPayload);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should call next with jwtPayload in context if no access codes are set', async () => {
|
|
54
|
-
const jwtPayload = {};
|
|
55
|
-
vi.spyOn(utils, 'getXorPayload').mockResolvedValue(jwtPayload);
|
|
56
|
-
|
|
57
|
-
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
58
|
-
router = createCaller(ctx);
|
|
59
|
-
|
|
60
|
-
const data = await router.protectedQuery();
|
|
61
|
-
|
|
62
|
-
expect(data).toEqual(jwtPayload);
|
|
63
|
-
});
|
|
64
|
-
it('should call next with jwtPayload in context if access codes is undefined', async () => {
|
|
65
|
-
const jwtPayload = {};
|
|
66
|
-
vi.spyOn(utils, 'getXorPayload').mockResolvedValue(jwtPayload);
|
|
67
|
-
|
|
68
|
-
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
69
|
-
router = createCaller(ctx);
|
|
70
|
-
|
|
71
|
-
const data = await router.protectedQuery();
|
|
72
|
-
|
|
73
|
-
expect(data).toEqual(jwtPayload);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { getXorPayload } from '@lobechat/utils/server';
|
|
2
|
-
import { TRPCError } from '@trpc/server';
|
|
3
|
-
|
|
4
|
-
import { edgeTrpc } from '../init';
|
|
5
|
-
|
|
6
|
-
export const jwtPayloadChecker = edgeTrpc.middleware(async (opts) => {
|
|
7
|
-
const { ctx } = opts;
|
|
8
|
-
|
|
9
|
-
if (!ctx.authorizationHeader) throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
10
|
-
|
|
11
|
-
const jwtPayload = getXorPayload(ctx.authorizationHeader);
|
|
12
|
-
|
|
13
|
-
return opts.next({ ctx: { jwtPayload } });
|
|
14
|
-
});
|