diff --git a/.gitignore b/.gitignore index 1ad6528..d2ae1c0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ vite.config.ts.timestamp-* # Sqlite src/lib/server/db/users.db* + +# Storage +minio-storage diff --git a/bun.lockb b/bun.lockb index cefd2ef..4f9038e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index c19a0e8..fe8ea6e 100644 --- a/package.json +++ b/package.json @@ -49,12 +49,14 @@ "@sveltejs/adapter-node": "^5.2.12", "@types/better-sqlite3": "^7.6.12", "@types/express": "^5.0.0", + "@types/minio": "^7.1.1", "better-auth": "^1.1.16", "better-sqlite3": "^11.8.1", "cassandra-driver": "^4.7.2", "express": "^4.21.2", "lucide-svelte": "^0.474.0", "markdown-it-highlightjs": "^4.2.0", + "minio": "^8.0.4", "mode-watcher": "^0.5.1", "socket.io": "^4.8.1", "socket.io-client": "^4.8.1", diff --git a/src/lib/components/forms/updatePFP.svelte b/src/lib/components/forms/updatePFP.svelte index 7bc9612..ecb0514 100644 --- a/src/lib/components/forms/updatePFP.svelte +++ b/src/lib/components/forms/updatePFP.svelte @@ -1,12 +1,26 @@ -
+
Upload Profile Image - +
diff --git a/src/lib/functions/generateReadableStream.ts b/src/lib/functions/generateReadableStream.ts new file mode 100644 index 0000000..6833587 --- /dev/null +++ b/src/lib/functions/generateReadableStream.ts @@ -0,0 +1,13 @@ +export async function generateStream(file: File): Promise { + try { + await fetch(`/api/upload/`, { + method: 'POST', + body: file, + }); + + return true; + } catch (e) { + console.error(`Error sending stream: ${(e as Error).message}`); + return false; + } +} diff --git a/src/lib/server/storage/minio-client.ts b/src/lib/server/storage/minio-client.ts new file mode 100644 index 0000000..d80c2a7 --- /dev/null +++ b/src/lib/server/storage/minio-client.ts @@ -0,0 +1,54 @@ +import * as Minio from 'minio'; +import { Readable } from 'stream'; +import { v4 } from 'uuid'; + +interface ClientParams { + endPoint: string; + port: number; + accessKey: string; + secretKey: string; + useSSL: boolean; +} + +class MinioClient { + private client: Minio.Client; + + constructor(params: ClientParams) { + this.client = new Minio.Client({ + endPoint: params.endPoint, + port: params.port, + useSSL: params.useSSL, + accessKey: params.accessKey, + secretKey: params.secretKey, + }); + } + + async uploadProfile(stream: Readable) { + try { + const bucket = 'profile-photos'; + if (await !this.client.bucketExists(bucket)) { + await this.client.makeBucket(bucket, 'us-east-1'); + console.log('Bucket "' + bucket + '" created in "us-east-1".'); + } + + const upload = await this.client.putObject(bucket, v4(), stream); + console.log(upload); + } catch (e) { + console.error(`Error uploading file: ${(e as Error).message}`); + } + } +} + +let fsClient: MinioClient | undefined; + +if (process.env.BUILDING !== 'true') { + fsClient = new MinioClient({ + endPoint: 'localhost', + port: 9000, + accessKey: 'minioadmin', + secretKey: 'minioadmin', + useSSL: false, + }); +} + +export { fsClient }; diff --git a/src/routes/(server)/api/upload/+server.ts b/src/routes/(server)/api/upload/+server.ts new file mode 100644 index 0000000..088d2f1 --- /dev/null +++ b/src/routes/(server)/api/upload/+server.ts @@ -0,0 +1,3 @@ +export const POST = async () => { + return new Response(undefined, { status: 204 }); +};