diff --git a/.github/workflows/desktop-pr-build.yml b/.github/workflows/desktop-pr-build.yml index c1aa843660..9db3ce637f 100644 --- a/.github/workflows/desktop-pr-build.yml +++ b/.github/workflows/desktop-pr-build.yml @@ -2,6 +2,7 @@ name: Desktop PR Build on: pull_request: + pull_request_target: types: [synchronize, labeled, unlabeled] # PR 更新或标签变化时触发 # 确保同一时间只运行一个相同的 workflow,取消正在进行的旧的运行 @@ -10,7 +11,9 @@ concurrency: cancel-in-progress: true # Add default permissions -permissions: read-all +permissions: + contents: write + pull-requests: write env: PR_TAG_PREFIX: pr- # PR 构建版本的前缀标识 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d51836e386..9277860047 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,12 +1,14 @@ name: Publish Docker Image permissions: contents: read + pull-requests: write on: workflow_dispatch: release: types: [published] pull_request: + pull_request_target: types: [synchronize, labeled, unlabeled] concurrency: @@ -52,9 +54,10 @@ jobs: - name: Generate PR metadata if: github.event_name == 'pull_request' id: pr_meta + env: + BRANCH_NAME: ${{ github.head_ref }} run: | - branch_name="${{ github.head_ref }}" - sanitized_branch=$(echo "${branch_name}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g') + sanitized_branch=$(echo "${BRANCH_NAME}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g') echo "pr_tag=${sanitized_branch}-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Docker meta @@ -131,9 +134,10 @@ jobs: - name: Generate PR metadata if: github.event_name == 'pull_request' id: pr_meta + env: + BRANCH_NAME: ${{ github.head_ref }} run: | - branch_name="${{ github.head_ref }}" - sanitized_branch=$(echo "${branch_name}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g') + sanitized_branch=$(echo "${BRANCH_NAME}" | sed -E 's/[^a-zA-Z0-9_.-]+/-/g') echo "pr_tag=${sanitized_branch}-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Docker meta diff --git a/apps/desktop/src/main/utils/next-electron-rsc.ts b/apps/desktop/src/main/utils/next-electron-rsc.ts index b40bdc86ba..ebd77e5e0b 100644 --- a/apps/desktop/src/main/utils/next-electron-rsc.ts +++ b/apps/desktop/src/main/utils/next-electron-rsc.ts @@ -1,6 +1,6 @@ // copy from https://github.com/kirill-konshin/next-electron-rsc import { serialize as serializeCookie } from 'cookie'; -import { type Protocol, type Session, protocol } from 'electron'; +import { type Protocol, type Session } from 'electron'; import type { NextConfig } from 'next'; import type NextNodeServer from 'next/dist/server/next-server'; import assert from 'node:assert'; @@ -202,6 +202,11 @@ export function createHandler({ if (!isDev) { logger.info('Initializing Next.js app for production'); + + // https://github.com/lobehub/lobe-chat/pull/9851 + // @ts-expect-error + // noinspection JSConstantReassignment + process.env.NODE_ENV = 'production'; const next = require(resolve.sync('next', { basedir: standaloneDir })); // @see https://github.com/vercel/next.js/issues/64031#issuecomment-2078708340 @@ -209,10 +214,7 @@ export function createHandler({ .config as NextConfig; process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(config); - app = next({ - dev: false, - dir: standaloneDir, - }) as NextNodeServer; + app = next({ dir: standaloneDir }) as NextNodeServer; handler = app.getRequestHandler(); preparePromise = app.prepare(); diff --git a/next.config.ts b/next.config.ts index 3647951470..c3b0ab476e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -28,9 +28,6 @@ const nextConfig: NextConfig = { emotion: true, }, compress: isProd, - eslint: { - ignoreDuringBuilds: true, - }, experimental: { optimizePackageImports: [ 'emoji-mart', @@ -46,6 +43,7 @@ const nextConfig: NextConfig = { // so we need to disable it // refs: https://github.com/lobehub/lobe-chat/pull/7430 serverMinification: false, + turbopackFileSystemCacheForDev: true, webVitalsAttribution: ['CLS', 'LCP'], webpackBuildWorker: true, webpackMemoryOptimizations: true, @@ -273,6 +271,7 @@ const nextConfig: NextConfig = { // when external packages in dev mode with turbopack, this config will lead to bundle error serverExternalPackages: isProd ? ['@electric-sql/pglite', "pdfkit"] : ["pdfkit"], transpilePackages: ['pdfjs-dist', 'mermaid'], + turbopack: {}, typescript: { ignoreBuildErrors: true, diff --git a/package.json b/package.json index 2368f817a5..77ea812ce9 100644 --- a/package.json +++ b/package.json @@ -31,14 +31,14 @@ ], "scripts": { "prebuild": "tsx scripts/prebuild.mts && npm run lint", - "build": "cross-env NODE_OPTIONS=--max-old-space-size=6144 next build", + "build": "cross-env NODE_OPTIONS=--max-old-space-size=6144 next build --webpack", "postbuild": "npm run build-sitemap && npm run build-migrate-db", "build-migrate-db": "bun run db:migrate", "build-sitemap": "tsx ./scripts/buildSitemapIndex/index.ts", - "build:analyze": "NODE_OPTIONS=--max-old-space-size=6144 ANALYZE=true next build", - "build:docker": "npm run prebuild && NODE_OPTIONS=--max-old-space-size=6144 DOCKER=true next build && npm run build-sitemap", + "build:analyze": "NODE_OPTIONS=--max-old-space-size=6144 ANALYZE=true next build --webpack", + "build:docker": "npm run prebuild && NODE_OPTIONS=--max-old-space-size=6144 DOCKER=true next build --webpack && npm run build-sitemap", "prebuild:electron": "cross-env NEXT_PUBLIC_IS_DESKTOP_APP=1 tsx scripts/prebuild.mts", - "build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 NEXT_PUBLIC_SERVICE_MODE=server next build", + "build:electron": "cross-env NODE_OPTIONS=--max-old-space-size=6144 NEXT_PUBLIC_IS_DESKTOP_APP=1 NEXT_PUBLIC_SERVICE_MODE=server next build --webpack", "clean:node_modules": "bash -lc 'set -e; echo \"Removing all node_modules...\"; rm -rf node_modules; pnpm -r exec rm -rf node_modules; rm -rf apps/desktop/node_modules; echo \"All node_modules removed.\"'", "db:generate": "drizzle-kit generate && npm run db:generate-client && npm run workflow:dbml", "db:generate-client": "tsx ./scripts/migrateClientDB/compile-migrations.ts", @@ -50,9 +50,9 @@ "desktop:build-local": "npm run desktop:build-next && npm run desktop:prepare-dist && npm run build-local --prefix=./apps/desktop", "desktop:build-next": "npm run build:electron", "desktop:prepare-dist": "tsx scripts/electronWorkflow/moveNextStandalone.ts", - "dev": "next dev --turbopack -p 3010", - "dev:desktop": "next dev --turbopack -p 3015", - "dev:mobile": "next dev --turbopack -p 3018", + "dev": "next dev -p 3010", + "dev:desktop": "next dev -p 3015", + "dev:mobile": "next dev -p 3018", "docs:i18n": "lobe-i18n md && npm run lint:md && npm run lint:mdx && prettier -c --write locales/**/*", "docs:seo": "lobe-seo && npm run lint:mdx", "e2e": "cd e2e && npm run test:smoke", @@ -123,9 +123,6 @@ "eslint --fix" ] }, - "overrides": { - "mdast-util-gfm-autolink-literal": "2.0.0" - }, "dependencies": { "@ant-design/icons": "^5.6.1", "@ant-design/pro-components": "^2.8.10", @@ -174,7 +171,7 @@ "@lobehub/ui": "^2.13.2", "@modelcontextprotocol/sdk": "^1.20.0", "@neondatabase/serverless": "^1.0.2", - "@next/third-parties": "^15.5.4", + "@next/third-parties": "^16.0.1", "@opentelemetry/exporter-jaeger": "^2.1.0", "@opentelemetry/winston-transport": "^0.18.0", "@react-pdf/renderer": "^4.3.0", @@ -235,7 +232,7 @@ "model-bank": "workspace:*", "modern-screenshot": "^4.6.6", "nanoid": "^5.1.6", - "next": "~15.3.5", + "next": "^16.0.1", "next-auth": "5.0.0-beta.30", "next-mdx-remote": "^5.0.0", "nextjs-toploader": "^3.9.17", @@ -261,9 +258,9 @@ "pwa-install-handler": "^2.6.3", "query-string": "^9.3.1", "random-words": "^2.0.1", - "react": "^19.2.0", + "react": "19.2.0", "react-confetti": "^6.4.0", - "react-dom": "^19.2.0", + "react-dom": "19.2.0", "react-fast-marquee": "^1.6.5", "react-hotkeys-hook": "^5.1.0", "react-i18next": "^15.7.4", @@ -313,8 +310,8 @@ "@lobehub/lint": "^1.26.2", "@lobehub/market-types": "^1.11.4", "@lobehub/seo-cli": "^1.7.0", - "@next/bundle-analyzer": "^15.5.4", - "@next/eslint-plugin-next": "^15.5.4", + "@next/bundle-analyzer": "^16.0.1", + "@next/eslint-plugin-next": "^15.5.6", "@peculiar/webcrypto": "^1.5.0", "@playwright/test": "^1.49.1", "@prettier/sync": "^0.6.1", @@ -335,8 +332,8 @@ "@types/oidc-provider": "^9.5.0", "@types/pdfkit": "^0.17.3", "@types/pg": "^8.15.5", - "@types/react": "^19.2.2", - "@types/react-dom": "^19.2.1", + "@types/react": "19.2.2", + "@types/react-dom": "19.2.2", "@types/rtl-detect": "^1.0.3", "@types/semver": "^7.7.1", "@types/systemjs": "^6.15.3", @@ -399,9 +396,6 @@ "pnpm": { "onlyBuiltDependencies": [ "@vercel/speed-insights" - ], - "overrides": { - "mdast-util-gfm-autolink-literal": "2.0.0" - } + ] } } diff --git a/packages/electron-client-ipc/package.json b/packages/electron-client-ipc/package.json index 4b5d1f090f..2d3da06b77 100644 --- a/packages/electron-client-ipc/package.json +++ b/packages/electron-client-ipc/package.json @@ -3,5 +3,8 @@ "version": "1.0.0", "private": true, "main": "src/index.ts", - "types": "src/index.ts" + "types": "src/index.ts", + "peerDependencies": { + "react": "^19" + } } diff --git a/packages/file-loaders/package.json b/packages/file-loaders/package.json index 4db5527562..5f83688d97 100644 --- a/packages/file-loaders/package.json +++ b/packages/file-loaders/package.json @@ -28,6 +28,7 @@ "@napi-rs/canvas": "^0.1.70", "@xmldom/xmldom": "^0.9.8", "concat-stream": "^2.0.0", + "debug": "^4.3.4", "mammoth": "^1.8.0", "officeparser": "5.1.1", "pdfjs-dist": "4.10.38", diff --git a/src/app/(backend)/webapi/revalidate/route.ts b/src/app/(backend)/webapi/revalidate/route.ts index 3f7bf3e4f7..73f609dcce 100644 --- a/src/app/(backend)/webapi/revalidate/route.ts +++ b/src/app/(backend)/webapi/revalidate/route.ts @@ -18,7 +18,7 @@ export const GET = async (request: NextRequest) => { return NextResponse.json('tag query parameter is required', { status: 400 }); } - revalidateTag(tag); + revalidateTag(tag, 'max'); return Response.json({ now: Date.now(), revalidated: true }); }; diff --git a/src/app/[variants]/layout.tsx b/src/app/[variants]/layout.tsx index 2a4b01642a..ef09137d2a 100644 --- a/src/app/[variants]/layout.tsx +++ b/src/app/[variants]/layout.tsx @@ -73,6 +73,7 @@ export const generateViewport = async (props: DynamicLayoutProps): ResolvingView return { ...dynamicScale, + colorScheme: null, initialScale: 1, minimumScale: 1, themeColor: [ diff --git a/src/app/sitemap.tsx b/src/app/sitemap.tsx index 1b4cc19665..2a491ee779 100644 --- a/src/app/sitemap.tsx +++ b/src/app/sitemap.tsx @@ -47,7 +47,13 @@ export function parsePaginatedId(id: string): { page?: number; type: SitemapType return { type: id as SitemapType }; } -export default async function sitemap({ id }: { id: string }): Promise { +export default async function sitemap({ + id: idPromise, +}: { + id: string; +}): Promise { + const id = await idPromise; + const { type, page } = parsePaginatedId(id); const sitemapModule = new Sitemap(); diff --git a/src/middleware.ts b/src/proxy.ts similarity index 100% rename from src/middleware.ts rename to src/proxy.ts diff --git a/tsconfig.json b/tsconfig.json index 0df184ce79..abfb3a7058 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "baseUrl": ".", "types": ["vitest/globals", "@serwist/next/typings"], @@ -41,5 +41,12 @@ ".temp", "e2e" ], - "include": ["**/*.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next-env.d.ts"] + "include": [ + "**/*.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "next-env.d.ts", + ".next/dev/types/**/*.ts" + ] }