mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-18 05:18:31 +00:00
@@ -51,7 +51,7 @@
|
||||
"@typescript/native-preview": "7.0.0-dev.20250711.1",
|
||||
"consola": "^3.1.0",
|
||||
"cookie": "^1.0.2",
|
||||
"electron": "^37.2.0",
|
||||
"electron": "^37.4.0",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-is": "^3.0.0",
|
||||
"electron-log": "^5.3.3",
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
|
||||
import type { NextRequest } from 'next/server';
|
||||
|
||||
import { pino } from '@/libs/logger';
|
||||
import { createLambdaContext } from '@/libs/trpc/lambda/context';
|
||||
import { desktopRouter } from '@/server/routers/desktop';
|
||||
|
||||
const handler = (req: NextRequest) =>
|
||||
fetchRequestHandler({
|
||||
/**
|
||||
* @link https://trpc.io/docs/v11/context
|
||||
*/
|
||||
createContext: () => createLambdaContext(req),
|
||||
|
||||
endpoint: '/trpc/desktop',
|
||||
|
||||
onError: ({ error, path, type }) => {
|
||||
pino.info(`Error in tRPC handler (desktop) on path: ${path}, type: ${type}`);
|
||||
console.error(error);
|
||||
},
|
||||
|
||||
req,
|
||||
router: desktopRouter,
|
||||
});
|
||||
|
||||
export { handler as GET, handler as POST };
|
||||
@@ -0,0 +1,10 @@
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe('Desktop TRPC Route', () => {
|
||||
it('should have desktop directory', () => {
|
||||
const desktopPath = join(__dirname, 'desktop');
|
||||
expect(existsSync(desktopPath)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
'use client';
|
||||
|
||||
import { ActionIcon, SideNav } from '@lobehub/ui';
|
||||
import { Cog, DatabaseIcon } from 'lucide-react';
|
||||
import { memo, useState } from 'react';
|
||||
import { Flexbox } from 'react-layout-kit';
|
||||
|
||||
import { BRANDING_NAME } from '@/const/branding';
|
||||
import PostgresViewer from '@/features/DevPanel/PostgresViewer';
|
||||
import SystemInspector from '@/features/DevPanel/SystemInspector';
|
||||
import { useStyles } from '@/features/DevPanel/features/FloatPanel';
|
||||
import { electronStylish } from '@/styles/electron';
|
||||
|
||||
const DevTools = memo(() => {
|
||||
const { styles, theme, cx } = useStyles();
|
||||
|
||||
const items = [
|
||||
{
|
||||
children: <PostgresViewer />,
|
||||
icon: <DatabaseIcon size={16} />,
|
||||
key: 'Postgres Viewer',
|
||||
},
|
||||
{
|
||||
children: <SystemInspector />,
|
||||
icon: <Cog size={16} />,
|
||||
key: 'System Status',
|
||||
},
|
||||
];
|
||||
|
||||
const [tab, setTab] = useState<string>(items[0].key);
|
||||
|
||||
return (
|
||||
<Flexbox height={'100%'} style={{ overflow: 'hidden', position: 'relative' }} width={'100%'}>
|
||||
<Flexbox
|
||||
align={'center'}
|
||||
className={cx(`panel-drag-handle`, styles.header, electronStylish.draggable)}
|
||||
horizontal
|
||||
justify={'center'}
|
||||
>
|
||||
<Flexbox align={'baseline'} gap={6} horizontal>
|
||||
<b>{BRANDING_NAME} Dev Tools</b>
|
||||
<span style={{ color: theme.colorTextDescription }}>/</span>
|
||||
<span style={{ color: theme.colorTextDescription }}>{tab}</span>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
<Flexbox
|
||||
height={'100%'}
|
||||
horizontal
|
||||
style={{ background: theme.colorBgLayout, overflow: 'hidden', position: 'relative' }}
|
||||
width={'100%'}
|
||||
>
|
||||
<SideNav
|
||||
bottomActions={[]}
|
||||
style={{
|
||||
background: 'transparent',
|
||||
width: 48,
|
||||
}}
|
||||
topActions={items.map((item) => (
|
||||
<ActionIcon
|
||||
active={tab === item.key}
|
||||
icon={item.icon}
|
||||
key={item.key}
|
||||
onClick={() => setTab(item.key)}
|
||||
title={item.key}
|
||||
tooltipProps={{
|
||||
placement: 'right',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
{items.map((item) => (
|
||||
<Flexbox
|
||||
flex={1}
|
||||
height={'100%'}
|
||||
key={item.key}
|
||||
style={{
|
||||
display: tab === item.key ? 'flex' : 'none',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
{item.children}
|
||||
</Flexbox>
|
||||
))}
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
);
|
||||
});
|
||||
|
||||
export default DevTools;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { NuqsAdapter } from 'nuqs/adapters/next/app';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { isDesktop } from '@/const/version';
|
||||
import GlobalLayout from '@/layout/GlobalProvider';
|
||||
import { ServerConfigStoreProvider } from '@/store/serverConfig/Provider';
|
||||
|
||||
interface RootLayoutProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const RootLayout = async ({ children }: RootLayoutProps) => {
|
||||
if (!isDesktop) return notFound();
|
||||
|
||||
return (
|
||||
<html dir="ltr" suppressHydrationWarning>
|
||||
<body>
|
||||
<NuqsAdapter>
|
||||
<ServerConfigStoreProvider>
|
||||
<GlobalLayout appearance={'auto'} isMobile={false} locale={''}>
|
||||
{children}
|
||||
</GlobalLayout>
|
||||
</ServerConfigStoreProvider>
|
||||
</NuqsAdapter>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
};
|
||||
|
||||
export default RootLayout;
|
||||
Reference in New Issue
Block a user