11import { Client , type RemoveOptions , type CopyConditions , type LifecycleConfig } from 'minio' ;
22import {
3- defaultS3Options ,
43 type ExtensionType ,
5- Mimes ,
64 type CreatePostPresignedUrlOptions ,
75 type CreatePostPresignedUrlParams ,
86 type CreatePostPresignedUrlResult ,
97 type S3BucketName ,
10- type S3Options
8+ type S3OptionsType
119} from '../type' ;
12- import type { BucketBasicOperationsType } from '../interface ' ;
13- import { createObjectKey , createTempObjectKey } from '../helpers' ;
10+ import { defaultS3Options , Mimes } from '../constants ' ;
11+ import { createObjectKey } from '../helpers' ;
1412import path from 'node:path' ;
15- import { MongoS3TTL } from 'common/ file/s3TTL /schema' ;
13+ import { MongoS3TTL } from '../../ file/s3Ttl /schema' ;
1614
17- export class S3BaseBucket implements BucketBasicOperationsType {
18- public client : Client ;
15+ export class S3BaseBucket {
16+ private _client : Client ;
17+ private _externalClient : Client | undefined ;
1918
2019 /**
2120 *
@@ -26,17 +25,32 @@ export class S3BaseBucket implements BucketBasicOperationsType {
2625 constructor (
2726 private readonly _bucket : S3BucketName ,
2827 private readonly afterInits ?: ( ( ) => Promise < void > | void ) [ ] ,
29- public options : Partial < S3Options > = defaultS3Options
28+ public options : Partial < S3OptionsType > = defaultS3Options
3029 ) {
3130 options = { ...defaultS3Options , ...options } ;
32- this . options = options as S3Options ;
33- this . client = new Client ( options as S3Options ) ;
31+ this . options = options ;
32+ this . _client = new Client ( options as S3OptionsType ) ;
33+
34+ if ( this . options . externalBaseURL ) {
35+ const externalBaseURL = new URL ( this . options . externalBaseURL ) ;
36+ const endpoint = externalBaseURL . hostname ;
37+ const useSSL = externalBaseURL . protocol === 'https' ;
38+
39+ this . _externalClient = new Client ( {
40+ useSSL : useSSL ,
41+ endPoint : endpoint ,
42+ port : options . port ,
43+ accessKey : options . accessKey ,
44+ secretKey : options . secretKey ,
45+ transportAgent : options . transportAgent
46+ } ) ;
47+ }
3448
3549 const init = async ( ) => {
3650 if ( ! ( await this . exist ( ) ) ) {
3751 await this . client . makeBucket ( this . _bucket ) ;
3852 }
39- await Promise . all ( this . afterInits ?. map ( ( afterInit ) => afterInit ( ) ) ?? [ ] ) ;
53+ await Promise . all ( afterInits ?. map ( ( afterInit ) => afterInit ( ) ) ?? [ ] ) ;
4054 } ;
4155 init ( ) ;
4256 }
@@ -45,10 +59,14 @@ export class S3BaseBucket implements BucketBasicOperationsType {
4559 return this . _bucket ;
4660 }
4761
48- async move ( src : string , dst : string , options ?: CopyConditions ) : Promise < void > {
62+ protected get client ( ) : Client {
63+ return this . _externalClient ?? this . _client ;
64+ }
65+
66+ move ( src : string , dst : string , options ?: CopyConditions ) : Promise < void > {
4967 const bucket = this . name ;
50- await this . client . copyObject ( bucket , dst , `/${ bucket } /${ src } ` , options ) ;
51- await this . delete ( src ) ;
68+ this . client . copyObject ( bucket , dst , `/${ bucket } /${ src } ` , options ) ;
69+ return this . delete ( src ) ;
5270 }
5371
5472 copy ( src : string , dst : string , options ?: CopyConditions ) : ReturnType < Client [ 'copyObject' ] > {
@@ -59,27 +77,19 @@ export class S3BaseBucket implements BucketBasicOperationsType {
5977 return this . client . bucketExists ( this . name ) ;
6078 }
6179
62- async delete ( objectKey : string , options ?: RemoveOptions ) : Promise < void > {
63- await this . client . removeObject ( this . name , objectKey , options ) ;
64- }
65-
66- get ( ) : Promise < void > {
67- throw new Error ( 'Method not implemented.' ) ;
68- }
69-
70- getLifecycle ( ) : Promise < LifecycleConfig | null > {
71- return this . client . getBucketLifecycle ( this . name ) ;
80+ delete ( objectKey : string , options ?: RemoveOptions ) : Promise < void > {
81+ return this . client . removeObject ( this . name , objectKey , options ) ;
7282 }
7383
7484 async createPostPresignedUrl (
7585 params : CreatePostPresignedUrlParams ,
7686 options : CreatePostPresignedUrlOptions = { }
7787 ) : Promise < CreatePostPresignedUrlResult > {
78- const { temporary , ttl = 7 * 24 } = options ;
88+ const { expiredHours } = options ;
7989 const ext = path . extname ( params . filename ) . toLowerCase ( ) as ExtensionType ;
8090 const contentType = Mimes [ ext ] ?? 'application/octet-stream' ;
8191 const maxFileSize = this . options . maxFileSize as number ;
82- const key = temporary ? createTempObjectKey ( params ) : createObjectKey ( params ) ;
92+ const key = createObjectKey ( params ) ;
8393
8494 const policy = this . client . newPostPolicy ( ) ;
8595 policy . setKey ( key ) ;
@@ -88,17 +98,19 @@ export class S3BaseBucket implements BucketBasicOperationsType {
8898 policy . setContentLengthRange ( 1 , maxFileSize ) ;
8999 policy . setExpires ( new Date ( Date . now ( ) + 10 * 60 * 1000 ) ) ;
90100 policy . setUserMetaData ( {
91- filename : encodeURIComponent ( params . filename ) ,
92- visibility : params . visibility
101+ 'content-type' : contentType ,
102+ 'content-disposition' : `attachment; filename="${ encodeURIComponent ( params . filename ) } "` ,
103+ 'origin-filename' : encodeURIComponent ( params . filename ) ,
104+ 'upload-time' : new Date ( ) . toISOString ( )
93105 } ) ;
94106
95107 const { formData, postURL } = await this . client . presignedPostPolicy ( policy ) ;
96108
97- if ( temporary ) {
109+ if ( expiredHours ) {
98110 await MongoS3TTL . create ( {
99111 minioKey : key ,
100112 bucketName : this . name ,
101- expiredTime : new Date ( Date . now ( ) + ttl * 3.6e6 )
113+ expiredTime : new Date ( Date . now ( ) + expiredHours * 3.6e6 )
102114 } ) ;
103115 }
104116
0 commit comments