chore(deps): upgrade to nextjs 16 (#2203)

* chore(deps): upgrade to nextjs 16

* upgraded fumadocs

* ensure vercel uses bun

* fix build

* fix bui;d

* remove redundant vercel.json
This commit is contained in:
Waleed
2025-12-04 17:55:37 -08:00
committed by GitHub
parent 1642ed754b
commit dcbdcb43aa
20 changed files with 260 additions and 148 deletions
+1 -4
View File
@@ -1,4 +1,4 @@
import { findNeighbour } from 'fumadocs-core/server'
import { findNeighbour } from 'fumadocs-core/page-tree'
import defaultMdxComponents from 'fumadocs-ui/mdx'
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page'
import { ChevronLeft, ChevronRight } from 'lucide-react'
@@ -186,9 +186,6 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
footer: <TOCFooter />,
single: false,
}}
article={{
className: 'scroll-smooth max-sm:pb-16',
}}
tableOfContentPopover={{
style: 'clerk',
enabled: true,
@@ -1,7 +1,7 @@
'use client'
import { type ReactNode, useEffect, useState } from 'react'
import type { PageTree } from 'fumadocs-core/server'
import type { Folder, Item, Separator } from 'fumadocs-core/page-tree'
import { ChevronRight } from 'lucide-react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
@@ -11,7 +11,7 @@ function isActive(url: string, pathname: string, nested = true): boolean {
return url === pathname || (nested && pathname.startsWith(`${url}/`))
}
export function SidebarItem({ item }: { item: PageTree.Item }) {
export function SidebarItem({ item }: { item: Item }) {
const pathname = usePathname()
const active = isActive(item.url, pathname, false)
@@ -33,15 +33,7 @@ export function SidebarItem({ item }: { item: PageTree.Item }) {
)
}
export function SidebarFolder({
item,
level,
children,
}: {
item: PageTree.Folder
level: number
children: ReactNode
}) {
export function SidebarFolder({ item, children }: { item: Folder; children: ReactNode }) {
const pathname = usePathname()
const hasActiveChild = checkHasActiveChild(item, pathname)
const [open, setOpen] = useState(hasActiveChild)
@@ -112,7 +104,7 @@ export function SidebarFolder({
)
}
export function SidebarSeparator({ item }: { item: PageTree.Separator }) {
export function SidebarSeparator({ item }: { item: Separator }) {
return (
<p className='mt-4 mb-1.5 px-2.5 font-semibold text-[10px] text-gray-500/80 uppercase tracking-wide dark:text-gray-500'>
{item.name}
@@ -120,7 +112,7 @@ export function SidebarSeparator({ item }: { item: PageTree.Separator }) {
)
}
function checkHasActiveChild(node: PageTree.Folder, pathname: string): boolean {
function checkHasActiveChild(node: Folder, pathname: string): boolean {
if (node.index && isActive(node.index.url, pathname)) {
return true
}
+2 -3
View File
@@ -2,9 +2,8 @@ import type { InferPageType } from 'fumadocs-core/source'
import type { source } from '@/lib/source'
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed')
return `# ${page.data.title} (${page.url})
${page.data.description || ''}
${page.data.content || ''}`
${processed}`
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { loader } from 'fumadocs-core/source'
import { docs } from '@/.source'
import { docs } from '@/.source/server'
import { i18n } from './i18n'
export const source = loader({
+5 -2
View File
@@ -16,10 +16,13 @@ const config = {
destination: '/introduction',
permanent: true,
},
]
},
async rewrites() {
return [
{
source: '/docs/:path*.mdx',
source: '/:path*.mdx',
destination: '/llms.mdx/:path*',
permanent: true,
},
]
},
+7 -7
View File
@@ -5,7 +5,7 @@
"license": "Apache-2.0",
"scripts": {
"dev": "next dev --port 3001",
"build": "NODE_OPTIONS='--max-old-space-size=8192' next build",
"build": "fumadocs-mdx && NODE_OPTIONS='--max-old-space-size=8192' next build",
"start": "next start",
"postinstall": "fumadocs-mdx",
"type-check": "tsc --noEmit"
@@ -14,14 +14,14 @@
"@tabler/icons-react": "^3.31.0",
"@vercel/og": "^0.6.5",
"clsx": "^2.1.1",
"fumadocs-core": "15.8.2",
"fumadocs-mdx": "11.10.1",
"fumadocs-ui": "15.8.2",
"fumadocs-core": "16.2.3",
"fumadocs-mdx": "14.1.0",
"fumadocs-ui": "16.2.3",
"lucide-react": "^0.511.0",
"next": "15.4.8",
"next": "16.0.7",
"next-themes": "^0.4.6",
"react": "19.1.0",
"react-dom": "19.1.0",
"react": "19.2.1",
"react-dom": "19.2.1",
"tailwind-merge": "^3.0.2"
},
"devDependencies": {
@@ -4,9 +4,9 @@ import { type NextFetchEvent, type NextRequest, NextResponse } from 'next/server
import { i18n } from '@/lib/i18n'
const { rewrite: rewriteLLM } = rewritePath('/docs/*path', '/llms.mdx/*path')
const i18nMiddleware = createI18nMiddleware(i18n)
const i18nProxy = createI18nMiddleware(i18n)
export default function middleware(request: NextRequest, event: NextFetchEvent) {
export default function proxy(request: NextRequest, event: NextFetchEvent) {
if (isMarkdownPreferred(request)) {
const result = rewriteLLM(request.nextUrl.pathname)
@@ -15,7 +15,7 @@ export default function middleware(request: NextRequest, event: NextFetchEvent)
}
}
return i18nMiddleware(request, event)
return i18nProxy(request, event)
}
export const config = {
+5
View File
@@ -2,6 +2,11 @@ import { defineConfig, defineDocs } from 'fumadocs-mdx/config'
export const docs = defineDocs({
dir: 'content/docs',
docs: {
postprocess: {
includeProcessedMarkdown: true,
},
},
})
export default defineConfig({
+4 -3
View File
@@ -13,10 +13,10 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"paths": {
"@/.source": ["./.source/index.ts"],
"@/.source/*": ["./.source/*"],
"@/*": ["./*"]
},
"plugins": [
@@ -31,7 +31,8 @@
"**/*.tsx",
".next/types/**/*.ts",
"content/docs/execution/index.mdx",
"content/docs/connections/index.mdx"
"content/docs/connections/index.mdx",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"]
}
@@ -14,13 +14,9 @@ export const dynamic = 'force-dynamic'
/**
* POST - Refresh an MCP server connection (requires any workspace permission)
*/
export const POST = withMcpAuth('read')(
async (
request: NextRequest,
{ userId, workspaceId, requestId },
{ params }: { params: { id: string } }
) => {
const serverId = params.id
export const POST = withMcpAuth<{ id: string }>('read')(
async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => {
const { id: serverId } = await params
try {
logger.info(
+3 -7
View File
@@ -15,13 +15,9 @@ export const dynamic = 'force-dynamic'
/**
* PATCH - Update an MCP server in the workspace (requires write or admin permission)
*/
export const PATCH = withMcpAuth('write')(
async (
request: NextRequest,
{ userId, workspaceId, requestId },
{ params }: { params: { id: string } }
) => {
const serverId = params.id
export const PATCH = withMcpAuth<{ id: string }>('write')(
async (request: NextRequest, { userId, workspaceId, requestId }, { params }) => {
const { id: serverId } = await params
try {
const body = getParsedBody(request) || (await request.json())
@@ -10,11 +10,10 @@ export async function GET(
{
params,
}: {
params: { id: string; executionId: string }
params: Promise<{ id: string; executionId: string }>
}
) {
const workflowId = params.id
const executionId = params.executionId
const { id: workflowId, executionId } = await params
const access = await validateWorkflowAccess(request, workflowId, false)
if (access.error) {
@@ -15,10 +15,10 @@ export async function GET(
{
params,
}: {
params: { id: string }
params: Promise<{ id: string }>
}
) {
const workflowId = params.id
const { id: workflowId } = await params
const access = await validateWorkflowAccess(request, workflowId, false)
if (access.error) {
+8 -6
View File
@@ -15,10 +15,10 @@ export interface McpAuthContext {
requestId: string
}
export type McpRouteHandler = (
export type McpRouteHandler<TParams = Record<string, string>> = (
request: NextRequest,
context: McpAuthContext,
...args: any[]
routeContext: { params: Promise<TParams> }
) => Promise<NextResponse>
interface AuthResult {
@@ -170,11 +170,13 @@ function getPermissionErrorMessage(permissionLevel: McpPermissionLevel): string
* @returns Middleware wrapper function
*
*/
export function withMcpAuth(permissionLevel: McpPermissionLevel = 'read') {
return function middleware(handler: McpRouteHandler) {
export function withMcpAuth<TParams = Record<string, string>>(
permissionLevel: McpPermissionLevel = 'read'
) {
return function middleware(handler: McpRouteHandler<TParams>) {
return async function wrappedHandler(
request: NextRequest,
...args: any[]
routeContext: { params: Promise<TParams> }
): Promise<NextResponse> {
const authResult = await validateMcpAuth(request, permissionLevel)
@@ -183,7 +185,7 @@ export function withMcpAuth(permissionLevel: McpPermissionLevel = 'read') {
}
try {
return await handler(request, (authResult as AuthResult).context, ...args)
return await handler(request, (authResult as AuthResult).context, routeContext)
} catch (error) {
logger.error(
`[${(authResult as AuthResult).context.requestId}] Error in MCP route handler:`,
+9 -4
View File
@@ -68,17 +68,22 @@ const nextConfig: NextConfig = {
typescript: {
ignoreBuildErrors: isTruthy(env.DOCKER_BUILD),
},
eslint: {
ignoreDuringBuilds: isTruthy(env.DOCKER_BUILD),
},
output: isTruthy(env.DOCKER_BUILD) ? 'standalone' : undefined,
turbopack: {
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'],
},
serverExternalPackages: ['unpdf', 'ffmpeg-static', 'fluent-ffmpeg'],
serverExternalPackages: [
'unpdf',
'ffmpeg-static',
'fluent-ffmpeg',
'pino',
'pino-pretty',
'thread-stream',
],
experimental: {
optimizeCss: true,
turbopackSourceMaps: false,
turbopackFileSystemCacheForDev: true,
},
...(isDev && {
allowedDevOrigins: [
+8 -8
View File
@@ -8,11 +8,11 @@
"node": ">=20.0.0"
},
"scripts": {
"dev": "next dev --turbo --port 3000",
"dev:classic": "next dev",
"dev": "next dev --port 3000",
"dev:webpack": "next dev --webpack",
"dev:sockets": "bun run socket-server/index.ts",
"dev:full": "concurrently -n \"App,Realtime\" -c \"cyan,magenta\" \"bun run dev\" \"bun run dev:sockets\"",
"build": "next build --turbopack",
"build": "next build",
"start": "next start",
"prepare": "cd ../.. && bun husky",
"test": "vitest run",
@@ -98,7 +98,7 @@
"mammoth": "^1.9.0",
"mysql2": "3.14.3",
"nanoid": "^3.3.7",
"next": "15.4.8",
"next": "16.0.7",
"next-mdx-remote": "^5.0.0",
"next-runtime-env": "3.3.0",
"next-themes": "^0.4.6",
@@ -108,9 +108,9 @@
"posthog-js": "1.268.9",
"posthog-node": "5.9.2",
"prismjs": "^1.30.0",
"react": "19.1.0",
"react": "19.2.1",
"react-colorful": "5.6.1",
"react-dom": "19.1.0",
"react-dom": "19.2.1",
"react-google-drive-picker": "^1.2.2",
"react-hook-form": "^7.54.2",
"react-markdown": "^10.1.0",
@@ -166,8 +166,8 @@
"sharp"
],
"overrides": {
"next": "15.4.8",
"@next/env": "15.4.8",
"next": "16.0.7",
"@next/env": "16.0.7",
"drizzle-orm": "^0.44.5",
"postgres": "^3.4.5"
}
+2 -2
View File
@@ -4,7 +4,7 @@ import { isHosted } from './lib/core/config/environment'
import { generateRuntimeCSP } from './lib/core/security/csp'
import { createLogger } from './lib/logs/console/logger'
const logger = createLogger('Middleware')
const logger = createLogger('Proxy')
const SUSPICIOUS_UA_PATTERNS = [
/^\s*$/, // Empty user agents
@@ -131,7 +131,7 @@ function handleSecurityFiltering(request: NextRequest): NextResponse | null {
return null
}
export async function middleware(request: NextRequest) {
export async function proxy(request: NextRequest) {
const url = request.nextUrl
const sessionCookie = getSessionCookie(request)
+3 -2
View File
@@ -35,7 +35,7 @@
"resolveJsonModule": true,
"isolatedModules": true,
"allowImportingTsExtensions": true,
"jsx": "preserve",
"jsx": "react-jsx",
"plugins": [
{
"name": "next"
@@ -48,7 +48,8 @@
".next/types/**/*.ts",
"../next-env.d.ts",
"telemetry.config.js",
"trigger.config.ts"
"trigger.config.ts",
".next/dev/types/**/*.ts"
],
"exclude": ["node_modules"]
}