|
@@ -1,227 +1,25 @@
|
|
|
'use client';
|
|
'use client';
|
|
|
|
|
|
|
|
-import SwaggerUI from 'swagger-ui-react';
|
|
|
|
|
-import 'swagger-ui-react/swagger-ui.css';
|
|
|
|
|
|
|
+import { useEffect } from 'react';
|
|
|
|
|
|
|
|
export default function ApiDocs() {
|
|
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 (
|
|
return (
|
|
|
<div className="min-h-screen bg-gray-50">
|
|
<div className="min-h-screen bg-gray-50">
|
|
@@ -234,7 +32,12 @@ export default function ApiDocs() {
|
|
|
<p className="text-gray-600 mb-6">
|
|
<p className="text-gray-600 mb-6">
|
|
|
Interactive API documentation for file upload and management endpoints.
|
|
Interactive API documentation for file upload and management endpoints.
|
|
|
</p>
|
|
</p>
|
|
|
- <SwaggerUI spec={spec} />
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ id="api-reference"
|
|
|
|
|
+ data-url="/api/openapi.json"
|
|
|
|
|
+ data-theme="default"
|
|
|
|
|
+ style={{ height: 'calc(100vh - 200px)' }}
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|