Sfoglia il codice sorgente

feat(api-docs): replace swagger-ui with scalar api reference

Replaced the static Swagger UI React component with dynamic Scalar API Reference
for improved API documentation experience. The new implementation loads the
Scalar reference dynamically via CDN and supports auto-generated OpenAPI
specification from `/api/openapi.json`.

- Removed swagger-ui-react and swagger-jsdoc dependencies
- Added @scalar/api-reference-react and @scalar/nextjs-api-reference packages
- Updated Next.js to latest version (15.4.1)
- Simplified API docs page with dynamic script loading
- Enhanced UI with modern Scalar design system
vidane 6 mesi fa
parent
commit
b5c7126a95
3 ha cambiato i file con 633 aggiunte e 370 eliminazioni
  1. 24 221
      app/api-docs/page.tsx
  2. 605 144
      package-lock.json
  3. 4 5
      package.json

+ 24 - 221
app/api-docs/page.tsx

@@ -1,227 +1,25 @@
 'use client';
 
-import SwaggerUI from 'swagger-ui-react';
-import 'swagger-ui-react/swagger-ui.css';
+import { useEffect } from 'react';
 
 export default function ApiDocs() {
-  const spec = {
-    openapi: '3.0.0',
-    info: {
-      title: 'Vtorio API',
-      version: '1.0.0',
-      description: 'File upload and management API for Vtorio application',
-    },
-    servers: [
-      {
-        url: process.env.NODE_ENV === 'production' 
-          ? 'https://your-domain.com' 
-          : 'http://localhost:3000',
-        description: process.env.NODE_ENV === 'production' ? 'Production server' : 'Development server',
-      },
-    ],
-    paths: {
-      '/api/upload': {
-        post: {
-          summary: 'Upload a file',
-          description: 'Upload a file to the server and store it in the database',
-          tags: ['Files'],
-          requestBody: {
-            required: true,
-            content: {
-              'multipart/form-data': {
-                schema: {
-                  type: 'object',
-                  properties: {
-                    file: {
-                      type: 'string',
-                      format: 'binary',
-                      description: 'The file to upload',
-                    },
-                  },
-                  required: ['file'],
-                },
-              },
-            },
-          },
-          responses: {
-            '200': {
-              description: 'File uploaded successfully',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      success: { type: 'boolean', example: true },
-                      file: {
-                        type: 'object',
-                        properties: {
-                          id: { type: 'string', example: 'clh123abc456' },
-                          filename: { type: 'string', example: 'document.pdf' },
-                          mimetype: { type: 'string', example: 'application/pdf' },
-                          size: { type: 'number', example: 1024000 },
-                          createdAt: { type: 'string', format: 'date-time' },
-                        },
-                      },
-                    },
-                  },
-                },
-              },
-            },
-            '400': {
-              description: 'Bad request - No file provided',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      success: { type: 'boolean', example: false },
-                      error: { type: 'string', example: 'No file provided' },
-                    },
-                  },
-                },
-              },
-            },
-            '500': {
-              description: 'Internal server error',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      success: { type: 'boolean', example: false },
-                      error: { type: 'string', example: 'Failed to upload file' },
-                    },
-                  },
-                },
-              },
-            },
-          },
-        },
-      },
-      '/api/files': {
-        get: {
-          summary: 'List all files',
-          description: 'Get a list of all uploaded files with metadata',
-          tags: ['Files'],
-          responses: {
-            '200': {
-              description: 'List of files retrieved successfully',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      success: { type: 'boolean', example: true },
-                      files: {
-                        type: 'array',
-                        items: {
-                          type: 'object',
-                          properties: {
-                            id: { type: 'string', example: 'clh123abc456' },
-                            filename: { type: 'string', example: 'document.pdf' },
-                            mimetype: { type: 'string', example: 'application/pdf' },
-                            size: { type: 'number', example: 1024000 },
-                            createdAt: { type: 'string', format: 'date-time' },
-                            updatedAt: { type: 'string', format: 'date-time' },
-                          },
-                        },
-                      },
-                    },
-                  },
-                },
-              },
-            },
-            '500': {
-              description: 'Internal server error',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      success: { type: 'boolean', example: false },
-                      error: { type: 'string', example: 'Failed to list files' },
-                    },
-                  },
-                },
-              },
-            },
-          },
-        },
-      },
-      '/api/files/{id}': {
-        get: {
-          summary: 'Download a file',
-          description: 'Download a specific file by its ID',
-          tags: ['Files'],
-          parameters: [
-            {
-              name: 'id',
-              in: 'path',
-              required: true,
-              description: 'The ID of the file to download',
-              schema: {
-                type: 'string',
-                example: 'clh123abc456',
-              },
-            },
-          ],
-          responses: {
-            '200': {
-              description: 'File downloaded successfully',
-              content: {
-                'application/octet-stream': {
-                  schema: {
-                    type: 'string',
-                    format: 'binary',
-                  },
-                },
-              },
-              headers: {
-                'Content-Type': {
-                  description: 'MIME type of the file',
-                  schema: { type: 'string' },
-                },
-                'Content-Disposition': {
-                  description: 'Attachment header with filename',
-                  schema: { type: 'string' },
-                },
-                'Content-Length': {
-                  description: 'Size of the file in bytes',
-                  schema: { type: 'integer' },
-                },
-              },
-            },
-            '404': {
-              description: 'File not found',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      error: { type: 'string', example: 'File not found' },
-                    },
-                  },
-                },
-              },
-            },
-            '500': {
-              description: 'Internal server error',
-              content: {
-                'application/json': {
-                  schema: {
-                    type: 'object',
-                    properties: {
-                      error: { type: 'string', example: 'Failed to retrieve file' },
-                    },
-                  },
-                },
-              },
-            },
-          },
-        },
-      },
-    },
-  };
+  useEffect(() => {
+    // Load Scalar API Reference dynamically
+    const script = document.createElement('script');
+    script.src = 'https://cdn.jsdelivr.net/npm/@scalar/api-reference@latest/dist/browser/standalone.js';
+    script.async = true;
+    document.body.appendChild(script);
+
+    const style = document.createElement('link');
+    style.rel = 'stylesheet';
+    style.href = 'https://cdn.jsdelivr.net/npm/@scalar/api-reference@latest/dist/browser/style.css';
+    document.head.appendChild(style);
+
+    return () => {
+      document.body.removeChild(script);
+      document.head.removeChild(style);
+    };
+  }, []);
 
   return (
     <div className="min-h-screen bg-gray-50">
@@ -234,7 +32,12 @@ export default function ApiDocs() {
             <p className="text-gray-600 mb-6">
               Interactive API documentation for file upload and management endpoints.
             </p>
-            <SwaggerUI spec={spec} />
+            <div 
+              id="api-reference"
+              data-url="/api/openapi.json"
+              data-theme="default"
+              style={{ height: 'calc(100vh - 200px)' }}
+            />
           </div>
         </div>
       </div>

File diff suppressed because it is too large
+ 605 - 144
package-lock.json


+ 4 - 5
package.json

@@ -10,14 +10,13 @@
   },
   "dependencies": {
     "@prisma/client": "^6.11.1",
-    "@types/swagger-ui-react": "^5.18.0",
-    "next": "15.1.6",
+    "@scalar/api-reference-react": "^0.7.33",
+    "@scalar/nextjs-api-reference": "^0.8.12",
+    "next": "^15.4.1",
     "pg": "^8.16.3",
     "prisma": "^6.11.1",
     "react": "^19.0.0",
-    "react-dom": "^19.0.0",
-    "swagger-jsdoc": "^6.2.8",
-    "swagger-ui-react": "^5.26.2"
+    "react-dom": "^19.0.0"
   },
   "devDependencies": {
     "@eslint/eslintrc": "^3",

Some files were not shown because too many files changed in this diff