♻️ refactor: remove base path (#9015)

* clean

* remove

* fix

* move config to envs

* remove envs
This commit is contained in:
Arvin Xu
2025-09-01 00:30:13 +08:00
committed by GitHub
parent 82f5abf83b
commit 2a5f8d712f
34 changed files with 29 additions and 74 deletions
@@ -37,13 +37,6 @@ When using the `random` mode, a random API Key will be selected from the availab
When using the `turn` mode, the API Keys will be retrieved in a polling manner according to the specified order.
### `NEXT_PUBLIC_BASE_PATH`
- Type: Optional
- Description: Add a `basePath` for LobeChat.
- Default: -
- Example: `/test`
### `DEFAULT_AGENT_CONFIG`
- Type: Optional
@@ -34,13 +34,6 @@ LobeChat 在部署时提供了一些额外的配置项,你可以使用环境
使用 `turn` 模式下,将按照填写的顺序,轮询获取得到 API Key。
### `NEXT_PUBLIC_BASE_PATH`
- 类型:可选
- 描述:为 LobeChat 添加 `basePath`
- 默认值: `-`
- 示例: `/test`
### `DEFAULT_AGENT_CONFIG`
- 类型:可选
-2
View File
@@ -13,7 +13,6 @@ const shouldUseCSP = process.env.ENABLED_CSP === '1';
// if you need to proxy the api endpoint to remote server
const basePath = process.env.NEXT_PUBLIC_BASE_PATH;
const isStandaloneMode = buildWithDocker || isDesktop;
const standaloneConfig: NextConfig = {
@@ -23,7 +22,6 @@ const standaloneConfig: NextConfig = {
const nextConfig: NextConfig = {
...(isStandaloneMode ? standaloneConfig : {}),
basePath,
compress: isProd,
experimental: {
optimizePackageImports: [
+1 -2
View File
@@ -1,7 +1,6 @@
import qs from 'query-string';
import urlJoin from 'url-join';
import { withBasePath } from '@/utils/basePath';
import { isDev } from '@/utils/env';
import { INBOX_SESSION_ID } from './session';
@@ -56,7 +55,7 @@ export const SESSION_CHAT_URL = (id: string = INBOX_SESSION_ID, mobile?: boolean
url: '/chat',
});
export const imageUrl = (filename: string) => withBasePath(`/images/${filename}`);
export const imageUrl = (filename: string) => `/images/${filename}`;
export const LOBE_URL_IMPORT_NAME = 'settings';
@@ -5,7 +5,7 @@ import { Langfuse } from 'langfuse';
import { LangfuseGenerationClient, LangfuseTraceClient } from 'langfuse-core';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import * as langfuseCfg from '@/config/langfuse';
import * as langfuseCfg from '@/envs/langfuse';
import { createTraceOptions } from '@/server/modules/ModelRuntime';
import { ChatStreamPayload, LobeOpenAI, ModelProvider, ModelRuntime } from '.';
-3
View File
@@ -1,3 +0,0 @@
import { appEnv } from '@/envs/app';
export const withBasePath = (path: string) => appEnv.NEXT_PUBLIC_BASE_PATH + path;
+1 -7
View File
@@ -2,16 +2,10 @@ import { BRANDING_LOGO_URL, BRANDING_NAME, ORG_NAME } from '@/const/branding';
import { DEFAULT_LANG } from '@/const/locale';
import { OFFICIAL_URL, OG_URL } from '@/const/url';
import { isCustomBranding, isCustomORG } from '@/const/version';
import { appEnv } from '@/envs/app';
import { translation } from '@/server/translation';
import { DynamicLayoutProps } from '@/types/next';
import { RouteVariants } from '@/utils/server/routeVariants';
const BASE_PATH = appEnv.NEXT_PUBLIC_BASE_PATH;
// if there is a base path, then we don't need the manifest
const noManifest = !!BASE_PATH;
export const generateMetadata = async (props: DynamicLayoutProps) => {
const locale = await RouteVariants.getLocale(props);
const { t } = await translation('metadata', locale);
@@ -32,7 +26,7 @@ export const generateMetadata = async (props: DynamicLayoutProps) => {
icon: '/favicon.ico?v=1',
shortcut: '/favicon-32x32.ico?v=1',
},
manifest: noManifest ? undefined : '/manifest.json',
manifest: '/manifest.json',
metadataBase: new URL(OFFICIAL_URL),
openGraph: {
description: t('chat.description', { appName: BRANDING_NAME }),
+1 -1
View File
@@ -1,6 +1,6 @@
import { GoogleAnalytics as GA } from '@next/third-parties/google';
import { analyticsEnv } from '@/config/analytics';
import { analyticsEnv } from '@/envs/analytics';
const GoogleAnalytics = () => <GA gaId={analyticsEnv.GOOGLE_ANALYTICS_MEASUREMENT_ID!} />;
@@ -1,7 +1,7 @@
import { ReactNode, memo } from 'react';
import { LobeAnalyticsProvider } from '@/components/Analytics/LobeAnalyticsProvider';
import { analyticsEnv } from '@/config/analytics';
import { analyticsEnv } from '@/envs/analytics';
import { isDev } from '@/utils/env';
type Props = {
+1 -1
View File
@@ -1,7 +1,7 @@
import { Analytics } from '@vercel/analytics/react';
import { memo } from 'react';
import { analyticsEnv } from '@/config/analytics';
import { analyticsEnv } from '@/envs/analytics';
const VercelAnalytics = memo(() => <Analytics debug={analyticsEnv.DEBUG_VERCEL_ANALYTICS} />);
+1 -1
View File
@@ -1,7 +1,7 @@
import dynamic from 'next/dynamic';
import { analyticsEnv } from '@/config/analytics';
import { isDesktop } from '@/const/version';
import { analyticsEnv } from '@/envs/analytics';
import Desktop from './Desktop';
import Google from './Google';
+1 -1
View File
@@ -1,7 +1,7 @@
// @vitest-environment node
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { analyticsEnv, getAnalyticsConfig } from '../analytics';
import { analyticsEnv, getAnalyticsConfig } from '../../envs/analytics';
beforeEach(() => {
// 在每个测试用例之前,清除所有的 console.warn mock
+1 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from 'vitest';
import { getDebugConfig } from '../debug';
import { getDebugConfig } from '../../envs/debug';
// 测试前重置 process.env
vi.stubGlobal('process', {
-3
View File
@@ -32,7 +32,6 @@ export const getAppConfig = () => {
return createEnv({
client: {
NEXT_PUBLIC_BASE_PATH: z.string(),
NEXT_PUBLIC_ENABLE_SENTRY: z.boolean(),
},
server: {
@@ -59,8 +58,6 @@ export const getAppConfig = () => {
SSRF_ALLOW_IP_ADDRESS_LIST: z.string().optional(),
},
runtimeEnv: {
NEXT_PUBLIC_BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH || '',
// Sentry
NEXT_PUBLIC_ENABLE_SENTRY: !!process.env.NEXT_PUBLIC_SENTRY_DSN,
+1 -1
View File
@@ -1,7 +1,7 @@
import { createServerAnalytics } from '@lobehub/analytics/server';
import { analyticsEnv } from '@/config/analytics';
import { BUSINESS_LINE } from '@/const/analytics';
import { analyticsEnv } from '@/envs/analytics';
import { isDev } from '@/utils/env';
export const serverAnalytics = createServerAnalytics({
+1 -1
View File
@@ -3,7 +3,7 @@ import { Langfuse } from 'langfuse';
import { CreateLangfuseTraceBody } from 'langfuse-core';
import { describe, expect, it, vi } from 'vitest';
import * as server from '@/config/langfuse';
import * as server from '@/envs/langfuse';
import { TraceClient } from './index';
+1 -1
View File
@@ -1,8 +1,8 @@
import { Langfuse } from 'langfuse';
import { CreateLangfuseTraceBody } from 'langfuse-core';
import { getLangfuseConfig } from '@/config/langfuse';
import { CURRENT_VERSION } from '@/const/version';
import { getLangfuseConfig } from '@/envs/langfuse';
import { TraceEventClient } from '@/libs/traces/event';
/**
+1 -2
View File
@@ -3,7 +3,6 @@ import superjson from 'superjson';
import { isDesktop } from '@/const/version';
import type { EdgeRouter } from '@/server/routers/edge';
import { withBasePath } from '@/utils/basePath';
import { fetchWithDesktopRemoteRPC } from '@/utils/electron/desktopRemoteRPCFetch';
export const edgeClient = createTRPCClient<EdgeRouter>({
@@ -21,7 +20,7 @@ export const edgeClient = createTRPCClient<EdgeRouter>({
},
maxURLLength: 2083,
transformer: superjson,
url: withBasePath('/trpc/edge'),
url: '/trpc/edge',
}),
],
});
+1 -1
View File
@@ -4,7 +4,7 @@ import { UnstructuredClient } from 'unstructured-client';
import { Strategy } from 'unstructured-client/sdk/models/shared';
import { PartitionResponse } from 'unstructured-client/src/sdk/models/operations';
import { knowledgeEnv } from '@/config/knowledge';
import { knowledgeEnv } from '@/envs/knowledge';
export enum ChunkingStrategy {
Basic = 'basic',
+1 -1
View File
@@ -4,8 +4,8 @@ import resourcesToBackend from 'i18next-resources-to-backend';
import { initReactI18next } from 'react-i18next';
import { isRtlLang } from 'rtl-detect';
import { getDebugConfig } from '@/config/debug';
import { DEFAULT_LANG } from '@/const/locale';
import { getDebugConfig } from '@/envs/debug';
import { normalizeLocale } from '@/locales/resources';
import { isDev, isOnServerSide } from '@/utils/env';
+1 -2
View File
@@ -1,6 +1,5 @@
import { describe, expect, it, vi } from 'vitest';
import { knowledgeEnv } from '@/config/knowledge';
import { getAppConfig } from '@/envs/app';
import { SystemEmbeddingConfig } from '@/types/knowledgeBase';
import { FilesConfigItem } from '@/types/user/settings/filesConfig';
@@ -13,7 +12,7 @@ vi.mock('@/envs/app', () => ({
getAppConfig: vi.fn(),
}));
vi.mock('@/config/knowledge', () => ({
vi.mock('@/envs/knowledge', () => ({
knowledgeEnv: {
DEFAULT_FILES_CONFIG: 'test_config',
},
+2 -2
View File
@@ -1,10 +1,10 @@
import { authEnv } from '@/config/auth';
import { fileEnv } from '@/config/file';
import { knowledgeEnv } from '@/config/knowledge';
import { langfuseEnv } from '@/config/langfuse';
import { enableNextAuth } from '@/const/auth';
import { isDesktop } from '@/const/version';
import { appEnv, getAppConfig } from '@/envs/app';
import { knowledgeEnv } from '@/envs/knowledge';
import { langfuseEnv } from '@/envs/langfuse';
import { parseSystemAgent } from '@/server/globalConfig/parseSystemAgent';
import { GlobalServerConfig } from '@/types/serverConfig';
+1 -1
View File
@@ -1,7 +1,7 @@
import { Strategy } from 'unstructured-client/sdk/models/shared';
import { knowledgeEnv } from '@/config/knowledge';
import type { NewChunkItem, NewUnstructuredChunkItem } from '@/database/schemas';
import { knowledgeEnv } from '@/envs/knowledge';
import { ChunkingLoader } from '@/libs/langchain';
import { ChunkingStrategy, Unstructured } from '@/libs/unstructured';
+1 -1
View File
@@ -2,7 +2,7 @@
import { TRPCError } from '@trpc/server';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { toolsEnv } from '@/config/tools';
import { toolsEnv } from '@/envs/tools';
import { SearXNGClient } from '@/server/services/search/impls/searxng/client';
import { SEARCH_SEARXNG_NOT_CONFIG } from '@/types/tool/search';
@@ -5,7 +5,7 @@ import { SearXNGClient } from './client';
import { hetongxue } from './fixtures/searXNG';
import { SearXNGImpl } from './index';
vi.mock('@/config/tools', () => ({
vi.mock('@/envs/tools', () => ({
toolsEnv: {
SEARXNG_URL: 'https://demo.com',
},
@@ -1,6 +1,6 @@
import { TRPCError } from '@trpc/server';
import { toolsEnv } from '@/config/tools';
import { toolsEnv } from '@/envs/tools';
import { SearXNGClient } from '@/server/services/search/impls/searxng/client';
import { SEARCH_SEARXNG_NOT_CONFIG, UniformSearchResponse } from '@/types/tool/search';
+1 -1
View File
@@ -1,7 +1,7 @@
import { CrawlImplType, Crawler } from '@lobechat/web-crawler';
import pMap from 'p-map';
import { toolsEnv } from '@/config/tools';
import { toolsEnv } from '@/envs/tools';
import { SearchParams } from '@/types/tool/search';
import { SearchImplType, SearchServiceImpl, createSearchServiceImpl } from './impls';
+5 -18
View File
@@ -1,20 +1,7 @@
/* eslint-disable sort-keys-fix/sort-keys-fix */
import { transform } from 'lodash-es';
import { withBasePath } from '@/utils/basePath';
const mapWithBasePath = <T extends object>(apis: T): T => {
return transform(apis, (result, value, key) => {
if (typeof value === 'string') {
// @ts-ignore
result[key] = withBasePath(value);
} else {
result[key] = value;
}
});
};
export const API_ENDPOINTS = mapWithBasePath({
export const API_ENDPOINTS = {
oauth: '/api/auth',
proxy: '/webapi/proxy',
@@ -26,11 +13,11 @@ export const API_ENDPOINTS = mapWithBasePath({
trace: '/webapi/trace',
// chat
chat: (provider: string) => withBasePath(`/webapi/chat/${provider}`),
chat: (provider: string) => `/webapi/chat/${provider}`,
// models
models: (provider: string) => withBasePath(`/webapi/models/${provider}`),
modelPull: (provider: string) => withBasePath(`/webapi/models/${provider}/pull`),
models: (provider: string) => `/webapi/models/${provider}`,
modelPull: (provider: string) => `/webapi/models/${provider}/pull`,
// image
images: (provider: string) => `/webapi/text-to-image/${provider}`,
@@ -42,4 +29,4 @@ export const API_ENDPOINTS = mapWithBasePath({
tts: '/webapi/tts/openai',
edge: '/webapi/tts/edge',
microsoft: '/webapi/tts/microsoft',
});
};
+1 -2
View File
@@ -2,7 +2,6 @@ import type { PartialDeep } from 'type-fest';
import { LOBE_URL_IMPORT_NAME } from '@/const/url';
import { UserSettings } from '@/types/user/settings';
import { withBasePath } from '@/utils/basePath';
class ShareService {
/**
@@ -11,7 +10,7 @@ class ShareService {
* @returns The share settings URL.
*/
public createShareSettingsUrl = (settings: PartialDeep<UserSettings>) => {
return withBasePath(`/?${LOBE_URL_IMPORT_NAME}=${encodeURI(JSON.stringify(settings))}`);
return `/?${LOBE_URL_IMPORT_NAME}=${encodeURI(JSON.stringify(settings))}`;
};
/**