|
1 | 1 | import { Client } from "minio"; |
2 | 2 | import { env } from "$lib/env/env.server"; |
3 | 3 |
|
4 | | -const url = new URL(env.S3_ENDPOINT); |
| 4 | +let _s3: Client | null = null; |
5 | 5 |
|
6 | | -export const s3 = new Client({ |
7 | | - endPoint: url.hostname, |
8 | | - port: url.port ? parseInt(url.port, 10) : url.protocol === "https:" ? 443 : 80, |
9 | | - useSSL: url.protocol === "https:", |
10 | | - accessKey: env.S3_ACCESS_KEY, |
11 | | - secretKey: env.S3_SECRET_KEY, |
| 6 | +function getS3(): Client { |
| 7 | + if (!_s3) { |
| 8 | + const url = new URL(env.S3_ENDPOINT); |
| 9 | + _s3 = new Client({ |
| 10 | + endPoint: url.hostname, |
| 11 | + port: url.port ? parseInt(url.port, 10) : url.protocol === "https:" ? 443 : 80, |
| 12 | + useSSL: url.protocol === "https:", |
| 13 | + accessKey: env.S3_ACCESS_KEY, |
| 14 | + secretKey: env.S3_SECRET_KEY, |
| 15 | + }); |
| 16 | + } |
| 17 | + return _s3; |
| 18 | +} |
| 19 | + |
| 20 | +// Lazy-initialized s3 client via Proxy |
| 21 | +export const s3: Client = new Proxy({} as Client, { |
| 22 | + get(_, prop) { |
| 23 | + const instance = getS3(); |
| 24 | + const value = instance[prop as keyof Client]; |
| 25 | + if (typeof value === "function") { |
| 26 | + return (value as (...args: unknown[]) => unknown).bind(instance); |
| 27 | + } |
| 28 | + return value; |
| 29 | + }, |
12 | 30 | }); |
13 | 31 |
|
14 | | -export const bucket = env.S3_BUCKET; |
| 32 | +export function getBucket(): string { |
| 33 | + return env.S3_BUCKET; |
| 34 | +} |
15 | 35 |
|
16 | 36 | // Ensure bucket exists and is public (for dev) |
17 | | -const publicPolicy = { |
18 | | - Version: "2012-10-17", |
19 | | - Statement: [ |
20 | | - { |
21 | | - Effect: "Allow", |
22 | | - Principal: { AWS: ["*"] }, |
23 | | - Action: ["s3:GetObject"], |
24 | | - Resource: [`arn:aws:s3:::${bucket}/*`], |
25 | | - }, |
26 | | - ], |
27 | | -}; |
28 | | - |
29 | 37 | let initialized = false; |
30 | 38 | export async function ensureBucket() { |
31 | 39 | if (initialized) return; |
32 | 40 | initialized = true; |
33 | 41 |
|
34 | | - const exists = await s3.bucketExists(bucket); |
| 42 | + const bucketName = env.S3_BUCKET; |
| 43 | + const publicPolicy = { |
| 44 | + Version: "2012-10-17", |
| 45 | + Statement: [ |
| 46 | + { |
| 47 | + Effect: "Allow", |
| 48 | + Principal: { AWS: ["*"] }, |
| 49 | + Action: ["s3:GetObject"], |
| 50 | + Resource: [`arn:aws:s3:::${bucketName}/*`], |
| 51 | + }, |
| 52 | + ], |
| 53 | + }; |
| 54 | + |
| 55 | + const exists = await s3.bucketExists(bucketName); |
35 | 56 | if (!exists) { |
36 | | - await s3.makeBucket(bucket); |
| 57 | + await s3.makeBucket(bucketName); |
37 | 58 | } |
38 | | - await s3.setBucketPolicy(bucket, JSON.stringify(publicPolicy)); |
| 59 | + await s3.setBucketPolicy(bucketName, JSON.stringify(publicPolicy)); |
39 | 60 | } |
0 commit comments