@@ -83,6 +83,7 @@ export const listS3Contents = async (
83
83
registeredFileTypes : IRegisteredFileTypes ,
84
84
path ?: string
85
85
) : Promise < Contents . IModel > => {
86
+ let isFile : boolean = false ;
86
87
const fileList : IContentsList = { } ;
87
88
const prefix = path ? PathExt . join ( root , path ) : root ;
88
89
@@ -106,14 +107,16 @@ export const listS3Contents = async (
106
107
c . Key !== path + '/' &&
107
108
c . Key !== root + '/' + path + '/'
108
109
) {
109
- const fileName = c
110
- . Key ! . replace (
111
- ( root ? root + '/' : '' ) + ( path ? path + '/' : '' ) ,
112
- ''
113
- )
114
- . split ( '/' ) [ 0 ] ;
110
+ let fileName = c . Key ! . replace (
111
+ ( root ? root + '/' : '' ) + ( path ? path + '/' : '' ) ,
112
+ ''
113
+ ) ;
114
+ const isDir : boolean =
115
+ fileName === fileName . split ( '/' ) [ 0 ] ? false : true ;
116
+ fileName = fileName . split ( '/' ) [ 0 ] ;
115
117
const [ fileType , fileMimeType , fileFormat ] = Private . getFileType (
116
118
PathExt . extname ( PathExt . basename ( fileName ) ) ,
119
+ isDir ,
117
120
registeredFileTypes
118
121
) ;
119
122
@@ -131,25 +134,37 @@ export const listS3Contents = async (
131
134
} ;
132
135
}
133
136
} ) ;
137
+ } else {
138
+ isFile = true ;
139
+ data = await getS3FileContents (
140
+ s3Client ,
141
+ bucketName ,
142
+ root ,
143
+ path ! ,
144
+ registeredFileTypes
145
+ ) ;
134
146
}
147
+
135
148
if ( isTruncated ) {
136
149
isTruncated = IsTruncated ;
137
150
}
138
151
command . input . ContinuationToken = NextContinuationToken ;
139
152
}
140
153
141
- data = {
142
- name : path ? PathExt . basename ( path ) : bucketName ,
143
- path : path ? path + '/' : bucketName ,
144
- last_modified : '' ,
145
- created : '' ,
146
- content : Object . values ( fileList ) ,
147
- format : 'json' ,
148
- mimetype : '' ,
149
- size : undefined ,
150
- writable : true ,
151
- type : 'directory'
152
- } ;
154
+ if ( isFile === false ) {
155
+ data = {
156
+ name : path ? PathExt . basename ( path ) : bucketName ,
157
+ path : path ? path + '/' : bucketName ,
158
+ last_modified : '' ,
159
+ created : '' ,
160
+ content : Object . values ( fileList ) ,
161
+ format : 'json' ,
162
+ mimetype : '' ,
163
+ size : undefined ,
164
+ writable : true ,
165
+ type : 'directory'
166
+ } ;
167
+ }
153
168
154
169
return data ;
155
170
} ;
@@ -184,6 +199,7 @@ export const getS3FileContents = async (
184
199
const date : string = response . LastModified ! . toISOString ( ) ;
185
200
const [ fileType , fileMimeType , fileFormat ] = Private . getFileType (
186
201
PathExt . extname ( PathExt . basename ( path ) ) ,
202
+ false ,
187
203
registeredFileTypes
188
204
) ;
189
205
@@ -243,12 +259,14 @@ export const createS3Object = async (
243
259
path : string ,
244
260
body : string | Blob ,
245
261
registeredFileTypes : IRegisteredFileTypes ,
262
+ isDir : boolean ,
246
263
options ?: Partial < Contents . IModel >
247
264
) : Promise < Contents . IModel > => {
248
265
path = PathExt . join ( root , path ) ;
249
266
250
267
const [ fileType , fileMimeType , fileFormat ] = Private . getFileType (
251
268
PathExt . extname ( PathExt . basename ( name ) ) ,
269
+ isDir ,
252
270
registeredFileTypes
253
271
) ;
254
272
@@ -386,6 +404,7 @@ export const checkS3Object = async (
386
404
* @param oldLocalPath: The old path of the object.
387
405
* @param newLocalPath: The new path of the object.
388
406
* @param newFileName: The new object name.
407
+ * @param isDir: Whether the object is a directory or a file.
389
408
* @param registeredFileTypes: The list containing all registered file types.
390
409
*
391
410
* @returns A promise which resolves with the new object contents model.
@@ -397,13 +416,12 @@ export const renameS3Objects = async (
397
416
oldLocalPath : string ,
398
417
newLocalPath : string ,
399
418
newFileName : string ,
419
+ isDir : boolean ,
400
420
registeredFileTypes : IRegisteredFileTypes
401
421
) : Promise < Contents . IModel > => {
402
422
newLocalPath = PathExt . join ( root , newLocalPath ) ;
403
423
oldLocalPath = PathExt . join ( root , oldLocalPath ) ;
404
424
405
- const isDir : boolean = await isDirectory ( s3Client , bucketName , oldLocalPath ) ;
406
-
407
425
if ( isDir ) {
408
426
newLocalPath = newLocalPath . substring ( 0 , newLocalPath . length - 1 ) ;
409
427
}
@@ -412,6 +430,7 @@ export const renameS3Objects = async (
412
430
413
431
const [ fileType , fileMimeType , fileFormat ] = Private . getFileType (
414
432
PathExt . extname ( PathExt . basename ( newFileName ) ) ,
433
+ isDir ,
415
434
registeredFileTypes
416
435
) ;
417
436
@@ -560,29 +579,45 @@ export const copyS3Objects = async (
560
579
561
580
const [ fileType , fileMimeType , fileFormat ] = Private . getFileType (
562
581
PathExt . extname ( PathExt . basename ( name ) ) ,
582
+ isDir ,
563
583
registeredFileTypes
564
584
) ;
565
585
566
- // retrieve information of new file
567
- const newFileContents = await s3Client . send (
568
- new GetObjectCommand ( {
569
- Bucket : newBucketName ?? bucketName ,
570
- Key : name + ( suffix ? suffix : '' )
571
- } )
572
- ) ;
586
+ try {
587
+ const newFileContents = await s3Client . send (
588
+ new GetObjectCommand ( {
589
+ Bucket : newBucketName ?? bucketName ,
590
+ Key : name + ( suffix ? suffix : '' )
591
+ } )
592
+ ) ;
573
593
574
- data = {
575
- name : PathExt . basename ( name ) ,
576
- path : name ,
577
- last_modified : newFileContents . LastModified ! . toISOString ( ) ,
578
- created : new Date ( ) . toISOString ( ) ,
579
- content : await newFileContents . Body ! . transformToString ( ) ,
580
- format : fileFormat as Contents . FileFormat ,
581
- mimetype : fileMimeType ,
582
- size : newFileContents . ContentLength ! ,
583
- writable : true ,
584
- type : fileType
585
- } ;
594
+ data = {
595
+ name : PathExt . basename ( name ) ,
596
+ path : name ,
597
+ last_modified : newFileContents . LastModified ! . toISOString ( ) ,
598
+ created : new Date ( ) . toISOString ( ) ,
599
+ content : await newFileContents . Body ! . transformToString ( ) ,
600
+ format : fileFormat as Contents . FileFormat ,
601
+ mimetype : fileMimeType ,
602
+ size : newFileContents . ContentLength ! ,
603
+ writable : true ,
604
+ type : fileType
605
+ } ;
606
+ } catch {
607
+ // object directory itself doesn't exist
608
+ data = {
609
+ name : PathExt . basename ( name ) ,
610
+ path : name ,
611
+ last_modified : new Date ( ) . toISOString ( ) ,
612
+ created : new Date ( ) . toISOString ( ) ,
613
+ content : [ ] ,
614
+ format : fileFormat as Contents . FileFormat ,
615
+ mimetype : fileMimeType ,
616
+ size : 0 ,
617
+ writable : true ,
618
+ type : fileType
619
+ } ;
620
+ }
586
621
587
622
return data ;
588
623
} ;
@@ -655,7 +690,8 @@ export async function isDirectory(
655
690
// listing contents given a path, to check if it is a directory
656
691
const command = new ListObjectsV2Command ( {
657
692
Bucket : bucketName ,
658
- Prefix : objectPath + '/'
693
+ Prefix :
694
+ objectPath [ objectPath . length - 1 ] === '/' ? objectPath : objectPath + '/'
659
695
} ) ;
660
696
661
697
const { Contents } = await s3Client . send ( command ) ;
@@ -669,18 +705,22 @@ export async function isDirectory(
669
705
namespace Private {
670
706
/**
671
707
* Helping function to define file type, mimetype and format based on file extension.
672
- * @param extension file extension (e.g.: txt, ipynb, csv)
673
- * @returns
708
+ * @param extension: File extension (e.g.: txt, ipynb, csv)
709
+ * @param isDir: Boolean showing if the object is a directory or a file
710
+ * @param registeredFileTypes: The list containing all registered file types.
711
+ * @returns The object type, mimetype and format.
674
712
*/
675
713
export function getFileType (
676
714
extension : string ,
715
+ isDir : boolean ,
677
716
registeredFileTypes : IRegisteredFileTypes
678
717
) {
679
- let fileType : string = 'text' ;
680
- let fileMimetype : string = 'text/plain' ;
681
- let fileFormat : string = 'text' ;
718
+ let fileType : string = isDir === false ? 'text' : 'directory' ;
719
+ let fileMimetype : string =
720
+ isDir === false ? 'text/plain' : 'text/directory' ;
721
+ let fileFormat : string = isDir === false ? 'text' : 'json' ;
682
722
683
- if ( registeredFileTypes [ extension ] ) {
723
+ if ( isDir === false && registeredFileTypes [ extension ] ) {
684
724
fileType = registeredFileTypes [ extension ] . fileType ;
685
725
fileMimetype = registeredFileTypes [ extension ] . fileMimeTypes [ 0 ] ;
686
726
fileFormat = registeredFileTypes [ extension ] . fileFormat ;
0 commit comments