feat: integrate MinIO for file storage and management
- Added MinIO as a dependency in package.json. - Updated FilePreview component to simplify file type checks. - Refactored file removal API to delete files from MinIO instead of the filesystem. - Modified file serving API to fetch files from MinIO. - Changed file upload API to upload files directly to MinIO and store metadata in the database. - Enhanced environment configuration to include MinIO settings. - Updated file type utility to handle file extensions more robustly. - Created a new utility for MinIO client configuration and bucket management.
This commit is contained in:
		
							parent
							
								
									8798764b89
								
							
						
					
					
						commit
						792b0eb275
					
				
							
								
								
									
										358
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										358
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -19,6 +19,7 @@ | ||||
|         "@trpc/server": "^11.0.0", | ||||
|         "dompurify": "^3.2.5", | ||||
|         "mermaid": "^11.6.0", | ||||
|         "minio": "^8.0.5", | ||||
|         "next": "^15.2.3", | ||||
|         "next-auth": "5.0.0-beta.25", | ||||
|         "react": "^19.0.0", | ||||
| @ -2817,6 +2818,13 @@ | ||||
|         "win32" | ||||
|       ] | ||||
|     }, | ||||
|     "node_modules/@zxing/text-encoding": { | ||||
|       "version": "0.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", | ||||
|       "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", | ||||
|       "license": "(Unlicense OR Apache-2.0)", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "node_modules/acorn": { | ||||
|       "version": "8.14.1", | ||||
|       "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", | ||||
| @ -3054,6 +3062,12 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/async": { | ||||
|       "version": "3.2.6", | ||||
|       "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", | ||||
|       "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/async-function": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", | ||||
| @ -3068,7 +3082,6 @@ | ||||
|       "version": "1.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", | ||||
|       "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "possible-typed-array-names": "^1.0.0" | ||||
| @ -3117,6 +3130,15 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/block-stream2": { | ||||
|       "version": "2.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", | ||||
|       "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "readable-stream": "^3.4.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/brace-expansion": { | ||||
|       "version": "1.1.11", | ||||
|       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", | ||||
| @ -3141,6 +3163,21 @@ | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/browser-or-node": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", | ||||
|       "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/buffer-crc32": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", | ||||
|       "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=8.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/busboy": { | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", | ||||
| @ -3156,7 +3193,6 @@ | ||||
|       "version": "1.0.8", | ||||
|       "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", | ||||
|       "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.0", | ||||
| @ -3175,7 +3211,6 @@ | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", | ||||
|       "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-errors": "^1.3.0", | ||||
| @ -3189,7 +3224,6 @@ | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", | ||||
|       "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.2", | ||||
| @ -4070,6 +4104,15 @@ | ||||
|         "url": "https://github.com/sponsors/wooorm" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/decode-uri-component": { | ||||
|       "version": "0.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", | ||||
|       "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=0.10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/deep-is": { | ||||
|       "version": "0.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", | ||||
| @ -4081,7 +4124,6 @@ | ||||
|       "version": "1.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", | ||||
|       "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-define-property": "^1.0.0", | ||||
| @ -4180,7 +4222,6 @@ | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", | ||||
|       "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.1", | ||||
| @ -4294,7 +4335,6 @@ | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", | ||||
|       "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -4304,7 +4344,6 @@ | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", | ||||
|       "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -4342,7 +4381,6 @@ | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", | ||||
|       "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-errors": "^1.3.0" | ||||
| @ -4901,6 +4939,12 @@ | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/eventemitter3": { | ||||
|       "version": "5.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", | ||||
|       "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/exsolve": { | ||||
|       "version": "1.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", | ||||
| @ -4964,6 +5008,24 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/fast-xml-parser": { | ||||
|       "version": "4.5.3", | ||||
|       "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", | ||||
|       "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", | ||||
|       "funding": [ | ||||
|         { | ||||
|           "type": "github", | ||||
|           "url": "https://github.com/sponsors/NaturalIntelligence" | ||||
|         } | ||||
|       ], | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "strnum": "^1.1.1" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "fxparser": "src/cli/cli.js" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/fastq": { | ||||
|       "version": "1.19.1", | ||||
|       "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", | ||||
| @ -5000,6 +5062,15 @@ | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/filter-obj": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", | ||||
|       "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/find-up": { | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", | ||||
| @ -5042,7 +5113,6 @@ | ||||
|       "version": "0.3.5", | ||||
|       "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", | ||||
|       "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "is-callable": "^1.2.7" | ||||
| @ -5073,7 +5143,6 @@ | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", | ||||
|       "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
| @ -5114,7 +5183,6 @@ | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", | ||||
|       "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.2", | ||||
| @ -5139,7 +5207,6 @@ | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", | ||||
|       "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "dunder-proto": "^1.0.1", | ||||
| @ -5236,7 +5303,6 @@ | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", | ||||
|       "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -5292,7 +5358,6 @@ | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", | ||||
|       "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-define-property": "^1.0.0" | ||||
| @ -5321,7 +5386,6 @@ | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", | ||||
|       "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -5334,7 +5398,6 @@ | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", | ||||
|       "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "has-symbols": "^1.0.3" | ||||
| @ -5350,7 +5413,6 @@ | ||||
|       "version": "2.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", | ||||
|       "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "function-bind": "^1.1.2" | ||||
| @ -5572,6 +5634,12 @@ | ||||
|         "node": ">=0.8.19" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/inherits": { | ||||
|       "version": "2.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", | ||||
|       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", | ||||
|       "license": "ISC" | ||||
|     }, | ||||
|     "node_modules/inline-style-parser": { | ||||
|       "version": "0.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", | ||||
| @ -5602,6 +5670,15 @@ | ||||
|         "node": ">=12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/ipaddr.js": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", | ||||
|       "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/is-alphabetical": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", | ||||
| @ -5626,6 +5703,22 @@ | ||||
|         "url": "https://github.com/sponsors/wooorm" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/is-arguments": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", | ||||
|       "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.2", | ||||
|         "has-tostringtag": "^1.0.2" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/is-array-buffer": { | ||||
|       "version": "3.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", | ||||
| @ -5718,7 +5811,6 @@ | ||||
|       "version": "1.2.7", | ||||
|       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", | ||||
|       "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -5818,7 +5910,6 @@ | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", | ||||
|       "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.3", | ||||
| @ -5912,7 +6003,6 @@ | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", | ||||
|       "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.2", | ||||
| @ -5995,7 +6085,6 @@ | ||||
|       "version": "1.1.15", | ||||
|       "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", | ||||
|       "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "which-typed-array": "^1.1.16" | ||||
| @ -6560,6 +6649,12 @@ | ||||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/lodash": { | ||||
|       "version": "4.17.21", | ||||
|       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", | ||||
|       "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/lodash-es": { | ||||
|       "version": "4.17.21", | ||||
|       "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", | ||||
| @ -6633,7 +6728,6 @@ | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", | ||||
|       "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -7536,6 +7630,27 @@ | ||||
|         "node": ">=8.6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/mime-db": { | ||||
|       "version": "1.52.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", | ||||
|       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/mime-types": { | ||||
|       "version": "2.1.35", | ||||
|       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", | ||||
|       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "mime-db": "1.52.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/minimatch": { | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", | ||||
| @ -7559,6 +7674,31 @@ | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/minio": { | ||||
|       "version": "8.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.5.tgz", | ||||
|       "integrity": "sha512-/vAze1uyrK2R/DSkVutE4cjVoAowvIQ18RAwn7HrqnLecLlMazFnY0oNBqfuoAWvu7mZIGX75AzpuV05TJeoHg==", | ||||
|       "license": "Apache-2.0", | ||||
|       "dependencies": { | ||||
|         "async": "^3.2.4", | ||||
|         "block-stream2": "^2.1.0", | ||||
|         "browser-or-node": "^2.1.1", | ||||
|         "buffer-crc32": "^1.0.0", | ||||
|         "eventemitter3": "^5.0.1", | ||||
|         "fast-xml-parser": "^4.4.1", | ||||
|         "ipaddr.js": "^2.0.1", | ||||
|         "lodash": "^4.17.21", | ||||
|         "mime-types": "^2.1.35", | ||||
|         "query-string": "^7.1.3", | ||||
|         "stream-json": "^1.8.0", | ||||
|         "through2": "^4.0.2", | ||||
|         "web-encoding": "^1.1.5", | ||||
|         "xml2js": "^0.5.0 || ^0.6.2" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": "^16 || ^18 || >=20" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/mlly": { | ||||
|       "version": "1.7.4", | ||||
|       "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", | ||||
| @ -8138,7 +8278,6 @@ | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", | ||||
|       "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @ -8393,6 +8532,24 @@ | ||||
|       ], | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/query-string": { | ||||
|       "version": "7.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", | ||||
|       "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "decode-uri-component": "^0.2.2", | ||||
|         "filter-obj": "^1.1.0", | ||||
|         "split-on-first": "^1.0.0", | ||||
|         "strict-uri-encode": "^2.0.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=6" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/queue-microtask": { | ||||
|       "version": "1.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", | ||||
| @ -8486,6 +8643,20 @@ | ||||
|         "react": ">=18" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/readable-stream": { | ||||
|       "version": "3.6.2", | ||||
|       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", | ||||
|       "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "inherits": "^2.0.3", | ||||
|         "string_decoder": "^1.1.1", | ||||
|         "util-deprecate": "^1.0.1" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/reflect.getprototypeof": { | ||||
|       "version": "1.0.10", | ||||
|       "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", | ||||
| @ -8731,6 +8902,26 @@ | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/safe-buffer": { | ||||
|       "version": "5.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", | ||||
|       "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", | ||||
|       "funding": [ | ||||
|         { | ||||
|           "type": "github", | ||||
|           "url": "https://github.com/sponsors/feross" | ||||
|         }, | ||||
|         { | ||||
|           "type": "patreon", | ||||
|           "url": "https://www.patreon.com/feross" | ||||
|         }, | ||||
|         { | ||||
|           "type": "consulting", | ||||
|           "url": "https://feross.org/support" | ||||
|         } | ||||
|       ], | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/safe-push-apply": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", | ||||
| @ -8752,7 +8943,6 @@ | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", | ||||
|       "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.2", | ||||
| @ -8772,6 +8962,12 @@ | ||||
|       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/sax": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", | ||||
|       "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", | ||||
|       "license": "ISC" | ||||
|     }, | ||||
|     "node_modules/scheduler": { | ||||
|       "version": "0.26.0", | ||||
|       "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", | ||||
| @ -8801,7 +8997,6 @@ | ||||
|       "version": "1.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", | ||||
|       "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "define-data-property": "^1.1.4", | ||||
| @ -9015,6 +9210,15 @@ | ||||
|         "url": "https://github.com/sponsors/wooorm" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/split-on-first": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", | ||||
|       "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/stable-hash": { | ||||
|       "version": "0.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", | ||||
| @ -9022,6 +9226,21 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/stream-chain": { | ||||
|       "version": "2.2.5", | ||||
|       "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", | ||||
|       "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", | ||||
|       "license": "BSD-3-Clause" | ||||
|     }, | ||||
|     "node_modules/stream-json": { | ||||
|       "version": "1.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", | ||||
|       "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", | ||||
|       "license": "BSD-3-Clause", | ||||
|       "dependencies": { | ||||
|         "stream-chain": "^2.2.5" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/streamsearch": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", | ||||
| @ -9030,6 +9249,24 @@ | ||||
|         "node": ">=10.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/strict-uri-encode": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", | ||||
|       "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/string_decoder": { | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", | ||||
|       "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "safe-buffer": "~5.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/string.prototype.includes": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", | ||||
| @ -9180,6 +9417,18 @@ | ||||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/strnum": { | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", | ||||
|       "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", | ||||
|       "funding": [ | ||||
|         { | ||||
|           "type": "github", | ||||
|           "url": "https://github.com/sponsors/NaturalIntelligence" | ||||
|         } | ||||
|       ], | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/style-to-js": { | ||||
|       "version": "1.1.16", | ||||
|       "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz", | ||||
| @ -9281,6 +9530,15 @@ | ||||
|         "node": ">=6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/through2": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", | ||||
|       "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "readable-stream": "3" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/tinyexec": { | ||||
|       "version": "0.3.2", | ||||
|       "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", | ||||
| @ -9690,6 +9948,19 @@ | ||||
|         "punycode": "^2.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/util": { | ||||
|       "version": "0.12.5", | ||||
|       "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", | ||||
|       "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "inherits": "^2.0.3", | ||||
|         "is-arguments": "^1.0.4", | ||||
|         "is-generator-function": "^1.0.7", | ||||
|         "is-typed-array": "^1.1.3", | ||||
|         "which-typed-array": "^1.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/util-deprecate": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", | ||||
| @ -9800,6 +10071,18 @@ | ||||
|       "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/web-encoding": { | ||||
|       "version": "1.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", | ||||
|       "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "util": "^0.12.3" | ||||
|       }, | ||||
|       "optionalDependencies": { | ||||
|         "@zxing/text-encoding": "0.9.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/web-namespaces": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", | ||||
| @ -9897,7 +10180,6 @@ | ||||
|       "version": "1.1.19", | ||||
|       "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", | ||||
|       "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "available-typed-arrays": "^1.0.7", | ||||
| @ -9925,6 +10207,28 @@ | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/xml2js": { | ||||
|       "version": "0.6.2", | ||||
|       "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", | ||||
|       "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "sax": ">=0.6.0", | ||||
|         "xmlbuilder": "~11.0.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=4.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/xmlbuilder": { | ||||
|       "version": "11.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", | ||||
|       "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=4.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/yocto-queue": { | ||||
|       "version": "0.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", | ||||
|  | ||||
| @ -31,6 +31,7 @@ | ||||
|     "@trpc/server": "^11.0.0", | ||||
|     "dompurify": "^3.2.5", | ||||
|     "mermaid": "^11.6.0", | ||||
|     "minio": "^8.0.5", | ||||
|     "next": "^15.2.3", | ||||
|     "next-auth": "5.0.0-beta.25", | ||||
|     "react": "^19.0.0", | ||||
|  | ||||
| @ -12,6 +12,8 @@ export function FilePreview({ fileId, fileType }: FilePreviewProps) { | ||||
|   const [mediaSrc, setMediaSrc] = useState<string | null>(null); | ||||
|   const [error, setError] = useState<string | null>(null); | ||||
| 
 | ||||
|   console.log("File Type:", fileType); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (!fileId) { | ||||
|       setError("File ID is required."); | ||||
| @ -53,7 +55,7 @@ export function FilePreview({ fileId, fileType }: FilePreviewProps) { | ||||
|     return <div>Loading...</div>; | ||||
|   } | ||||
| 
 | ||||
|   if (getFileType(fileType).startsWith("video")) { | ||||
|   if (fileType.startsWith("video")) { | ||||
|     return ( | ||||
|       <video | ||||
|         controls | ||||
| @ -64,7 +66,7 @@ export function FilePreview({ fileId, fileType }: FilePreviewProps) { | ||||
|       </video> | ||||
|     ); | ||||
|   } | ||||
|   if (getFileType(fileType).startsWith("audio")) { | ||||
|   if (fileType.startsWith("audio")) { | ||||
|     return ( | ||||
|       <audio | ||||
|         controls | ||||
| @ -75,29 +77,31 @@ export function FilePreview({ fileId, fileType }: FilePreviewProps) { | ||||
|       </audio> | ||||
|     ); | ||||
|   } | ||||
|   if (getFileType(fileType).startsWith("image")) { | ||||
|   if (fileType.startsWith("image")) { | ||||
|     return <img src={mediaSrc} alt="Media preview" className="max-w-full max-h-96 rounded-lg shadow-md" />; | ||||
|   } | ||||
| 
 | ||||
|   if (getFileType(fileType).startsWith("text")) { | ||||
|   if (fileType.startsWith("text")) { | ||||
|     return ( | ||||
|       <img src="/icons/files/text.svg" alt="Text file preview" className="max-w-full max-h-96 rounded-lg invert" /> | ||||
|     ); | ||||
|   } | ||||
|   if (getFileType(fileType).startsWith("archive")) { | ||||
|   if (fileType.startsWith("archive")) { | ||||
|     return ( | ||||
|       <img src="/icons/files/archive.svg" alt="Archive file preview" className="max-w-full max-h-96 rounded-lg invert" /> | ||||
|     ); | ||||
|   } | ||||
|   if (getFileType(fileType).startsWith("code") || getFileType(fileType).startsWith("markdown")) { | ||||
|   if (fileType.startsWith("code") || fileType.startsWith("markdown")) { | ||||
|     return ( | ||||
|       <img src="/icons/files/code.svg" alt="Code file preview" className="max-w-full max-h-96 rounded-lg invert" /> | ||||
|     ); | ||||
|   } | ||||
|   // if (getFileType(fileType).startsWith("markdown")) {
 | ||||
|   // if (fileType.startsWith("markdown")) {
 | ||||
|   //   return;      
 | ||||
|   //   }
 | ||||
| 
 | ||||
|   // log file type
 | ||||
|   console.log("Unsupported file type:", fileType); | ||||
| 
 | ||||
|   return; | ||||
| } | ||||
| @ -1,13 +1,11 @@ | ||||
| import { NextResponse } from "next/server"; | ||||
| import { db } from "~/server/db"; | ||||
| import { auth } from "~/server/auth"; | ||||
| import path from "path"; | ||||
| import { promises as fs } from "fs"; | ||||
| import { minioClient } from "~/utils/minioClient"; | ||||
| import { notifyClients } from "~/utils/notifyClients"; | ||||
| 
 | ||||
| export async function DELETE(req: Request) { | ||||
|   const session = await auth(); | ||||
| 
 | ||||
|   if (!session?.user) { | ||||
|     return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); | ||||
|   } | ||||
| @ -18,32 +16,25 @@ export async function DELETE(req: Request) { | ||||
|       return NextResponse.json({ error: "Invalid request body" }, { status: 400 }); | ||||
|     } | ||||
| 
 | ||||
|     const resource = await db.file.findUnique({ | ||||
|       where: { id: body.id }, | ||||
|     }); | ||||
| 
 | ||||
|     if (!resource) { | ||||
|     const file = await db.file.findUnique({ where: { id: body.id } }); | ||||
|     if (!file) { | ||||
|       return NextResponse.json({ error: "File not found" }, { status: 404 }); | ||||
|     } | ||||
| 
 | ||||
|     if (resource.uploadedById !== session.user.id) { | ||||
|     if (file.uploadedById !== session.user.id) { | ||||
|       return NextResponse.json({ error: "You are not authorized to delete this file" }, { status: 403 }); | ||||
|     } | ||||
| 
 | ||||
|     const filePath = path.join(process.cwd(), "uploads", path.basename(body.id)); | ||||
|     await fs.unlink(filePath).catch((err) => { | ||||
|       console.error("Error deleting file from filesystem:", err); | ||||
|     }); | ||||
|     const objectName = `${file.id}-${file.name}`; | ||||
|     await minioClient.removeObject(process.env.MINIO_BUCKET || "file-hosting", objectName); | ||||
| 
 | ||||
|     await db.file.delete({ | ||||
|       where: { id: body.id }, | ||||
|     }); | ||||
|     await db.file.delete({ where: { id: body.id } }); | ||||
| 
 | ||||
|     notifyClients({ type: "file-removed", fileId: body.id }); | ||||
| 
 | ||||
|     return NextResponse.json({ message: "File deleted successfully" }); | ||||
|   } catch (error) { | ||||
|     console.error("Error deleting file:", error); | ||||
|     console.error("Error deleting file from MinIO:", error); | ||||
|     return NextResponse.json({ error: "Failed to delete file" }, { status: 500 }); | ||||
|   } | ||||
| } | ||||
| @ -1,7 +1,6 @@ | ||||
| import { NextResponse } from "next/server"; | ||||
| import path from "path"; | ||||
| import { promises as fs } from "fs"; | ||||
| import { db } from "~/server/db"; | ||||
| import { minioClient } from "~/utils/minioClient"; | ||||
| import { getFileType } from "~/utils/fileType"; | ||||
| 
 | ||||
| export async function GET(req: Request) { | ||||
| @ -22,24 +21,31 @@ export async function GET(req: Request) { | ||||
|       return NextResponse.json({ error: "File not found" }, { status: 404 }); | ||||
|     } | ||||
| 
 | ||||
|     // Construct the file path
 | ||||
|     const filePath = path.join(process.cwd(), "uploads", file.id); | ||||
|     const bucketName = process.env.MINIO_BUCKET || "file-hosting"; | ||||
|     const objectName = `${file.id}-${file.name}`; // Construct the object name in MinIO
 | ||||
| 
 | ||||
|     // Read the file from the filesystem
 | ||||
|     const fileBuffer = await fs.readFile(filePath); | ||||
| 
 | ||||
|     const mimeType = getFileType(path.extname(file.name)); // Get the MIME type based on the file extension
 | ||||
|     // Fetch the file from MinIO
 | ||||
|     const stream = await minioClient.getObject(bucketName, objectName); | ||||
| 
 | ||||
|     const mimeType = getFileType(file.name); // Get the MIME type based on the file extension
 | ||||
| 
 | ||||
|     // Return the file as a binary response
 | ||||
|     return new Response(fileBuffer, { | ||||
|     const readableStream = new ReadableStream({ | ||||
|       start(controller) { | ||||
|         stream.on("data", (chunk) => controller.enqueue(chunk)); | ||||
|         stream.on("end", () => controller.close()); | ||||
|         stream.on("error", (err) => controller.error(err)); | ||||
|       }, | ||||
|     }); | ||||
| 
 | ||||
|     return new Response(readableStream, { | ||||
|       headers: { | ||||
|         "Content-Type": mimeType, | ||||
|         "Content-Disposition": `inline; filename="${file.name}"`, | ||||
|       }, | ||||
|     }); | ||||
|   } catch (error) { | ||||
|     console.error("Error fetching file:", error); | ||||
|     console.error("Error fetching file from MinIO:", error); | ||||
|     return NextResponse.json({ error: "Failed to fetch file" }, { status: 500 }); | ||||
|   } | ||||
| } | ||||
| @ -1,12 +1,10 @@ | ||||
| import { NextResponse } from "next/server"; | ||||
| import { promises as fs } from "fs"; | ||||
| import path from "path"; | ||||
| import { db } from "~/server/db"; | ||||
| import { auth } from "~/server/auth"; | ||||
| import Busboy from "busboy"; | ||||
| import { Readable } from "stream"; | ||||
| import { notifyClients } from "~/utils/notifyClients"; | ||||
| import crypto from "crypto"; | ||||
| import { db } from "~/server/db"; | ||||
| import { auth } from "~/server/auth"; | ||||
| import { minioClient, ensureBucketExists } from "~/utils/minioClient"; | ||||
| 
 | ||||
| export const config = { | ||||
|   api: { | ||||
| @ -16,15 +14,12 @@ export const config = { | ||||
| 
 | ||||
| export async function POST(req: Request) { | ||||
|   const session = await auth(); | ||||
|   // generate id for the file
 | ||||
|   const guid = crypto.randomUUID(); | ||||
| 
 | ||||
|   if (!session?.user) { | ||||
|     return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); | ||||
|   } | ||||
| 
 | ||||
|   const uploadDir = path.join(process.cwd(), "uploads"); | ||||
|   await fs.mkdir(uploadDir, { recursive: true }); | ||||
|   const bucketName = process.env.MINIO_BUCKET || "file-hosting"; | ||||
|   await ensureBucketExists(bucketName); | ||||
| 
 | ||||
|   return new Promise<Response>((resolve, reject) => { | ||||
|     const busboy = Busboy({ headers: { "content-type": req.headers.get("content-type") ?? "" } }); | ||||
| @ -35,57 +30,39 @@ export async function POST(req: Request) { | ||||
|       fileName = info.filename || "uploaded-file"; | ||||
|       const chunks: Buffer[] = []; | ||||
| 
 | ||||
|       // Check if a file with the same name already exists for the user
 | ||||
|       const existingFile = await db.file.findFirst({ | ||||
|         where: { | ||||
|           name: fileName, | ||||
|           uploadedById: session.user.id, | ||||
|         }, | ||||
|       }); | ||||
| 
 | ||||
|       if (existingFile) { | ||||
|         // Modify the file name to make it unique
 | ||||
|         const fileExtension = path.extname(fileName); | ||||
|         const baseName = path.basename(fileName, fileExtension); | ||||
|         fileName = `${baseName}-${Date.now()}${fileExtension}`; | ||||
|       } | ||||
|    | ||||
|       file.on("data", (chunk) => { | ||||
|         chunks.push(chunk); | ||||
|       }); | ||||
| 
 | ||||
|       file.on("end", () => { | ||||
|       file.on("end", async () => { | ||||
|         fileBuffer = Buffer.concat(chunks); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     busboy.on("finish", () => { | ||||
|       void (async () => { | ||||
|         // Generate a unique ID for the file
 | ||||
|         const fileId = crypto.randomUUID(); | ||||
|         const objectName = `${fileId}-${fileName}`; | ||||
| 
 | ||||
|         try { | ||||
|           const filePath = path.join(uploadDir, guid); | ||||
|           await fs.writeFile(filePath, fileBuffer); | ||||
|           // Upload the file to MinIO
 | ||||
|           await minioClient.putObject(bucketName, objectName, fileBuffer); | ||||
| 
 | ||||
|           // Save file metadata to the database
 | ||||
|           const newFile = await db.file.create({ | ||||
|             data: { | ||||
|               id: guid, | ||||
|               url: `/share?id=${guid}`, | ||||
|               id: fileId, | ||||
|               url: `/share?id=${fileId}`, | ||||
|               name: fileName, | ||||
|               size: fileBuffer.length, | ||||
|               extension: path.extname(fileName), | ||||
|               extension: info.mimeType, | ||||
|               uploadedById: session.user.id, | ||||
|             }, | ||||
|           }); | ||||
| 
 | ||||
|           // Notify clients about the new file
 | ||||
|           notifyClients({ type: "file-added", file: newFile }); | ||||
| 
 | ||||
|           resolve(NextResponse.json({ message: "File uploaded successfully" })); | ||||
|           resolve(NextResponse.json({ message: "File uploaded successfully", file: newFile })); | ||||
|         } catch (error) { | ||||
|           console.error("Error handling upload:", error); | ||||
|           resolve(NextResponse.json({ error: "Failed to upload file" }, { status: 500 })); | ||||
|           console.error("Error uploading file to MinIO:", error); | ||||
|           reject(new Error("Failed to upload file")); | ||||
|         } | ||||
|       })(); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     busboy.on("error", (error: unknown) => { | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/env.js
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/env.js
									
									
									
									
									
								
							| @ -19,7 +19,11 @@ export const env = createEnv({ | ||||
|     NODE_ENV: z | ||||
|       .enum(["development", "test", "production"]) | ||||
|       .default("development"), | ||||
|      | ||||
|     MINIO_ENDPOINT: z.string(), | ||||
|     MINIO_PORT: z.string(), | ||||
|     MINIO_ACCESS_KEY: z.string(), | ||||
|     MINIO_SECRET_KEY: z.string(), | ||||
|     MINIO_BUCKET: z.string(), | ||||
|   }, | ||||
| 
 | ||||
|   /** | ||||
| @ -43,6 +47,11 @@ export const env = createEnv({ | ||||
|     DATABASE_URL: process.env.DATABASE_URL, | ||||
|     NODE_ENV: process.env.NODE_ENV, | ||||
|     NEXT_PUBLIC_PAGE_URL: process.env.NEXT_PUBLIC_PAGE_URL, | ||||
|     MINIO_ENDPOINT: process.env.MINIO_ENDPOINT, | ||||
|     MINIO_PORT: process.env.MINIO_PORT, | ||||
|     MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, | ||||
|     MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, | ||||
|     MINIO_BUCKET: process.env.MINIO_BUCKET, | ||||
|   }, | ||||
|   /** | ||||
|    * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially | ||||
|  | ||||
| @ -1,31 +1,32 @@ | ||||
| // This function takes a file name as input and returns the file type based on its extension.
 | ||||
| 
 | ||||
| export function getFileType(extension: string): string { | ||||
| export function getFileType(fileName: string): string { | ||||
|     const extension = fileName.split(".").pop()?.toLowerCase(); | ||||
|     const fileTypes: Record<string, string> = { | ||||
|         ".mp4": "video/mp4", | ||||
|         ".webm": "video/webm", | ||||
|         ".ogg": "video/ogg", | ||||
|         ".jpg": "image/jpeg", | ||||
|         ".jpeg": "image/jpeg", | ||||
|         ".png": "image/png", | ||||
|         ".gif": "image/gif", | ||||
|         ".svg": "image/svg+xml", | ||||
|         ".mp3": "audio/mpeg", | ||||
|         ".wav": "audio/wav", | ||||
|         ".zip": "archive/zip", | ||||
|         ".rar": "archive/rar", | ||||
|         ".pdf": "text/pdf", | ||||
|         ".txt": "text/plain", | ||||
|         ".c": "code/c", | ||||
|         ".cpp": "code/cpp", | ||||
|         ".py": "code/python", | ||||
|         ".js": "code/javascript", | ||||
|         ".html": "code/html", | ||||
|         ".css": "code/css", | ||||
|         ".md": "markdown/markdown", | ||||
|         ".json": "code/json", | ||||
|         ".xml": "code/xml", | ||||
|         ".csv": "code/csv", | ||||
|         "mp4": "video/mp4", | ||||
|         "webm": "video/webm", | ||||
|         "ogg": "video/ogg", | ||||
|         "jpg": "image/jpeg", | ||||
|         "jpeg": "image/jpeg", | ||||
|         "png": "image/png", | ||||
|         "gif": "image/gif", | ||||
|         "svg": "image/svg+xml", | ||||
|         "mp3": "audio/mpeg", | ||||
|         "wav": "audio/wav", | ||||
|         "zip": "archive/zip", | ||||
|         "rar": "archive/rar", | ||||
|         "pdf": "text/pdf", | ||||
|         "txt": "text/plain", | ||||
|         "c": "code/c", | ||||
|         "cpp": "code/cpp", | ||||
|         "py": "code/python", | ||||
|         "js": "code/javascript", | ||||
|         "html": "code/html", | ||||
|         "css": "code/css", | ||||
|         "md": "markdown/markdown", | ||||
|         "json": "code/json", | ||||
|         "xml": "code/xml", | ||||
|         "csv": "code/csv", | ||||
|     }; | ||||
|     return fileTypes[extension] || "unknown"; | ||||
|     return extension ? fileTypes[extension] || "unknown" : "unknown"; | ||||
|   }; | ||||
							
								
								
									
										19
									
								
								src/utils/minioClient.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/utils/minioClient.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| import { Client } from "minio"; | ||||
| import { env } from "~/env"; | ||||
| 
 | ||||
| export const minioClient = new Client({ | ||||
|   endPoint: env.MINIO_ENDPOINT, | ||||
|   port: parseInt(env.MINIO_PORT, 10), | ||||
|   useSSL: false, // Set to true if using HTTPS
 | ||||
|   accessKey: env.MINIO_ACCESS_KEY, | ||||
|   secretKey: env.MINIO_SECRET_KEY, | ||||
| }); | ||||
| 
 | ||||
| // Ensure the bucket exists
 | ||||
| export async function ensureBucketExists(bucketName: string) { | ||||
|   const exists = await minioClient.bucketExists(bucketName); | ||||
|   if (!exists) { | ||||
|     await minioClient.makeBucket(bucketName, "us-east-1"); | ||||
|     console.log(`Bucket "${bucketName}" created.`); | ||||
|   } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user