MAI CALL - step 3
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@repo/storage",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rimraf .turbo node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.787.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.787.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/config": "workspace:*",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export type { ObjectStorage } from './interface.js';
|
||||
export { MinioStorage } from './minio.js';
|
||||
|
||||
import { MinioStorage } from './minio.js';
|
||||
|
||||
export function makeStorage(): MinioStorage {
|
||||
const endpoint = process.env['S3_ENDPOINT'];
|
||||
const region = process.env['S3_REGION'] ?? 'us-east-1';
|
||||
const bucket = process.env['S3_BUCKET'];
|
||||
const accessKey = process.env['S3_ACCESS_KEY'];
|
||||
const secretKey = process.env['S3_SECRET_KEY'];
|
||||
const forcePathStyle = process.env['S3_FORCE_PATH_STYLE'] === 'true';
|
||||
|
||||
if (!endpoint || !bucket || !accessKey || !secretKey) {
|
||||
throw new Error(
|
||||
'Missing required env vars: S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY',
|
||||
);
|
||||
}
|
||||
|
||||
return new MinioStorage({ endpoint, region, bucket, accessKey, secretKey, forcePathStyle });
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface ObjectStorage {
|
||||
signPut(key: string, contentType: string, byteSize: number, ttlSec: number): Promise<{ url: string; expiresAt: Date }>;
|
||||
signGet(key: string, ttlSec: number): Promise<{ url: string; expiresAt: Date }>;
|
||||
delete(key: string): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
S3Client,
|
||||
PutObjectCommand,
|
||||
GetObjectCommand,
|
||||
DeleteObjectCommand,
|
||||
} from '@aws-sdk/client-s3';
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
||||
import type { ObjectStorage } from './interface.js';
|
||||
|
||||
interface MinioStorageOptions {
|
||||
endpoint: string;
|
||||
region: string;
|
||||
bucket: string;
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
forcePathStyle: boolean;
|
||||
}
|
||||
|
||||
export class MinioStorage implements ObjectStorage {
|
||||
private readonly client: S3Client;
|
||||
private readonly bucket: string;
|
||||
|
||||
constructor(opts: MinioStorageOptions) {
|
||||
this.bucket = opts.bucket;
|
||||
this.client = new S3Client({
|
||||
endpoint: opts.endpoint,
|
||||
region: opts.region,
|
||||
credentials: {
|
||||
accessKeyId: opts.accessKey,
|
||||
secretAccessKey: opts.secretKey,
|
||||
},
|
||||
forcePathStyle: opts.forcePathStyle,
|
||||
});
|
||||
}
|
||||
|
||||
async signPut(
|
||||
key: string,
|
||||
contentType: string,
|
||||
_byteSize: number,
|
||||
ttlSec: number,
|
||||
): Promise<{ url: string; expiresAt: Date }> {
|
||||
const cmd = new PutObjectCommand({
|
||||
Bucket: this.bucket,
|
||||
Key: key,
|
||||
ContentType: contentType,
|
||||
});
|
||||
const url = await getSignedUrl(this.client, cmd, { expiresIn: ttlSec });
|
||||
return { url, expiresAt: new Date(Date.now() + ttlSec * 1000) };
|
||||
}
|
||||
|
||||
async signGet(key: string, ttlSec: number): Promise<{ url: string; expiresAt: Date }> {
|
||||
const cmd = new GetObjectCommand({ Bucket: this.bucket, Key: key });
|
||||
const url = await getSignedUrl(this.client, cmd, { expiresIn: ttlSec });
|
||||
return { url, expiresAt: new Date(Date.now() + ttlSec * 1000) };
|
||||
}
|
||||
|
||||
async delete(key: string): Promise<void> {
|
||||
await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "@repo/config/tsconfig/library.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user