diff --git a/next.config.js b/next.config.js index 88cc54a..6ccaaac 100644 --- a/next.config.js +++ b/next.config.js @@ -11,6 +11,25 @@ const nextConfig = { } ] }, + // Suppress React strict mode warnings for third-party components + webpack: (config, { dev, isServer }) => { + if (dev) { + // Suppress specific warnings from swagger-ui-react in development + config.ignoreWarnings = [ + ...(config.ignoreWarnings || []), + /UNSAFE_componentWillReceiveProps/, + /componentWillReceiveProps/, + /UNSAFE_componentWillMount/, + /componentWillMount/, + /UNSAFE_componentWillUpdate/, + /componentWillUpdate/, + /strict mode is not recommended/, + /ModelCollapse/, + /OperationContainer/, + ] + } + return config + }, } module.exports = nextConfig \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 25b5f70..3ca32b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "@types/react-dom": "^19.1.8", "autoprefixer": "^10.4.21", "postcss": "^8.5.6", + "string-replace-loader": "^3.2.0", "tailwindcss": "^4.1.12", "typescript": "^5.9.2" } @@ -2007,6 +2008,54 @@ "node": ">= 14" } }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, "node_modules/ansi-regex": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", @@ -2974,6 +3023,23 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fast-xml-parser": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", @@ -5270,6 +5336,26 @@ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, + "node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -5588,6 +5674,22 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-replace-loader": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-3.2.0.tgz", + "integrity": "sha512-q7+F4DC6MAKkszF3ZQEuZ3dDH25wXPxFA0maTLk3TOTAYPLDgwqCeCKIvOd8xJhYYYl+EXusYRCyKIJliT/olg==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "webpack": "^5" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", diff --git a/package.json b/package.json index bbdc596..ff5f461 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@types/react-dom": "^19.1.8", "autoprefixer": "^10.4.21", "postcss": "^8.5.6", + "string-replace-loader": "^3.2.0", "tailwindcss": "^4.1.12", "typescript": "^5.9.2" } diff --git a/src/app/docs/page.tsx b/src/app/docs/page.tsx index bc116c2..47d094a 100644 --- a/src/app/docs/page.tsx +++ b/src/app/docs/page.tsx @@ -1,15 +1,9 @@ 'use client' import { useState, useEffect } from 'react' -import dynamic from 'next/dynamic' +import SwaggerUIWrapper from '@/components/SwaggerUIWrapper' import './swagger-ui-tailwind.css' -// Dynamically import Swagger UI to avoid SSR issues -const SwaggerUI = dynamic(() => import('swagger-ui-react'), { - ssr: false, - loading: () =>
Loading Swagger UI...
-}) - export default function ApiDocsPage() { const [spec, setSpec] = useState(null) const [error, setError] = useState(null) @@ -204,16 +198,8 @@ export default function ApiDocsPage() {
{/* Documentation Content */}
- { return req }} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index acb6b84..c1e49d1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' -import MainLayout from '@/components/MainLayout' +import ConditionalLayout from '@/components/ConditionalLayout' const inter = Inter({ subsets: ['latin'] }) @@ -18,7 +18,7 @@ export default function RootLayout({ return ( - {children} + {children} ) diff --git a/src/components/ConditionalLayout.tsx b/src/components/ConditionalLayout.tsx new file mode 100644 index 0000000..ee38144 --- /dev/null +++ b/src/components/ConditionalLayout.tsx @@ -0,0 +1,26 @@ +'use client' + +import { usePathname } from 'next/navigation' +import MainLayout from './MainLayout' + +interface ConditionalLayoutProps { + children: React.ReactNode +} + +export default function ConditionalLayout({ children }: ConditionalLayoutProps) { + const pathname = usePathname() + + // Routes that should not use the main layout (with sidebar) + const excludedRoutes = ['/docs'] + + const shouldUseMainLayout = !excludedRoutes.some(route => + pathname.startsWith(route) + ) + + if (shouldUseMainLayout) { + return {children} + } + + // For excluded routes, render children directly + return <>{children} +} \ No newline at end of file diff --git a/src/components/SwaggerUIWrapper.tsx b/src/components/SwaggerUIWrapper.tsx new file mode 100644 index 0000000..dd228ed --- /dev/null +++ b/src/components/SwaggerUIWrapper.tsx @@ -0,0 +1,78 @@ +'use client' + +import { useEffect } from 'react' +import dynamic from 'next/dynamic' + +// Dynamically import Swagger UI with SSR disabled +const SwaggerUIComponent = dynamic(() => import('swagger-ui-react'), { + ssr: false, + loading: () =>
Loading API Documentation...
+}) + +interface SwaggerUIWrapperProps { + spec: any + [key: string]: any +} + +export default function SwaggerUIWrapper({ spec, ...props }: SwaggerUIWrapperProps) { + useEffect(() => { + // Store original console methods + const originalError = console.error + const originalWarn = console.warn + + // Override console methods to filter out React strict mode warnings + const filterMessage = (message: any) => { + if (typeof message === 'string') { + return ( + message.includes('UNSAFE_componentWillReceiveProps') || + message.includes('componentWillReceiveProps') || + message.includes('UNSAFE_componentWillMount') || + message.includes('componentWillMount') || + message.includes('UNSAFE_componentWillUpdate') || + message.includes('componentWillUpdate') || + message.includes('strict mode is not recommended') || + message.includes('ModelCollapse') || + message.includes('OperationContainer') + ) + } + return false + } + + console.error = (...args) => { + if (!filterMessage(args[0])) { + originalError.apply(console, args) + } + } + + console.warn = (...args) => { + if (!filterMessage(args[0])) { + originalWarn.apply(console, args) + } + } + + // Cleanup function to restore original console methods + return () => { + console.error = originalError + console.warn = originalWarn + } + }, []) + + if (!spec) { + return null + } + + return ( + + ) +} \ No newline at end of file