mirror of
https://github.com/PeterMaquiran/tvone-api.git
synced 2026-04-19 00:37:51 +00:00
add moodules
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Client } from 'minio';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
@Injectable()
|
||||
export class MinioService implements OnModuleInit {
|
||||
private client: Client | null = null;
|
||||
private bucket: string;
|
||||
|
||||
constructor(private readonly config: ConfigService) {
|
||||
this.bucket = this.config.get<string>('minio.bucket', 'tvone');
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
const accessKey = this.config.get<string>('minio.accessKey', '');
|
||||
const secretKey = this.config.get<string>('minio.secretKey', '');
|
||||
if (!accessKey || !secretKey) {
|
||||
return;
|
||||
}
|
||||
this.client = new Client({
|
||||
endPoint: this.config.get<string>('minio.endpoint', 'localhost'),
|
||||
port: this.config.get<number>('minio.port', 9000),
|
||||
useSSL: this.config.get<boolean>('minio.useSsl', false),
|
||||
accessKey,
|
||||
secretKey,
|
||||
});
|
||||
const exists = await this.client.bucketExists(this.bucket).catch(() => false);
|
||||
if (!exists) {
|
||||
await this.client.makeBucket(this.bucket, '');
|
||||
}
|
||||
}
|
||||
|
||||
isConfigured(): boolean {
|
||||
return this.client !== null;
|
||||
}
|
||||
|
||||
async putObject(
|
||||
objectName: string,
|
||||
buffer: Buffer,
|
||||
contentType: string,
|
||||
): Promise<string> {
|
||||
if (!this.client) {
|
||||
throw new Error('MinIO is not configured (MINIO_ACCESS_KEY / MINIO_SECRET_KEY)');
|
||||
}
|
||||
await this.client.putObject(this.bucket, objectName, buffer, buffer.length, {
|
||||
'Content-Type': contentType,
|
||||
});
|
||||
return objectName;
|
||||
}
|
||||
|
||||
buildOriginalsKey(prefix: string, originalName: string): string {
|
||||
const safe = originalName.replace(/[^a-zA-Z0-9._-]/g, '_');
|
||||
return `${prefix}/${randomUUID()}-${safe}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { MinioService } from './minio.service';
|
||||
import { ThumborUrlService } from './thumbor-url.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [MinioService, ThumborUrlService],
|
||||
exports: [MinioService, ThumborUrlService],
|
||||
})
|
||||
export class StorageModule {}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
/**
|
||||
* Builds Thumbor-style URLs for the CDN/Varnish layer in front of Thumbor.
|
||||
* Example path segment: /800x0/smart/originals/articles/abc.jpg
|
||||
*/
|
||||
@Injectable()
|
||||
export class ThumborUrlService {
|
||||
constructor(private readonly config: ConfigService) {}
|
||||
|
||||
imageUrl(fileKey: string, options?: { width?: number; height?: number; smart?: boolean }) {
|
||||
const base = this.config.get<string>('thumbor.publicBaseUrl', '');
|
||||
if (!base) {
|
||||
return { path: `/${fileKey}`, full: null as string | null };
|
||||
}
|
||||
const w = options?.width ?? 0;
|
||||
const h = options?.height ?? 0;
|
||||
const smart = options?.smart !== false ? 'smart' : 'fit-in';
|
||||
const dims = `${w}x${h}`;
|
||||
const path = `/${dims}/${smart}/${fileKey}`;
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
|
||||
return { path, full: `${normalizedBase}${path}` };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user