@@ -23,11 +23,16 @@ import type {
2323} from "./types" ;
2424
2525/**
26- * Describe what this is
27- * TODO: Switch all @public to @alpha
28- * TODO: tag internal for itneral functions
26+ * Client for efficient transfer of objects to and from Amazon S3.
27+ * Provides methods to optimize uploading and downloading individual objects
28+ * as well as entire directories, with support for multipart operations,
29+ * concurrency control, and request cancellation.
30+ * Implements an eventTarget-based progress tracking system with methods to register,
31+ * dispatch, and remove listeners for transfer lifecycle events.
32+ *
2933 * @alpha
3034 */
35+
3136export class S3TransferManager implements IS3TransferManager {
3237 private static MIN_PART_SIZE = 5 * 1024 * 1024 ; // 5MB
3338 private static DEFAULT_PART_SIZE = 8 * 1024 * 1024 ; // 8MB
@@ -90,6 +95,16 @@ export class S3TransferManager implements IS3TransferManager {
9095 options ?: AddEventListenerOptions | boolean
9196 ) : void ;
9297 public addEventListener ( type : string , callback : EventListener , options ?: AddEventListenerOptions | boolean ) : void ;
98+ /**
99+ * Registers a callback function to be executed when a specific transfer event occurs.
100+ * Supports monitoring the full lifecycle of transfers.
101+ *
102+ * @param type - The type of event to listen for.
103+ * @param callback - Function to execute when the specified event occurs.
104+ * @param options - Optional configuration for event listener behavior.
105+ *
106+ * @alpha
107+ */
93108 public addEventListener ( type : string , callback : EventListener , options ?: AddEventListenerOptions | boolean ) : void {
94109 const eventType = type as keyof TransferEventListeners ;
95110 const listeners = this . eventListeners [ eventType ] ;
@@ -129,18 +144,18 @@ export class S3TransferManager implements IS3TransferManager {
129144 listeners . push ( updatedCallback ) ;
130145 }
131146
147+ public dispatchEvent ( event : Event & TransferEvent ) : boolean ;
148+ public dispatchEvent ( event : Event & TransferCompleteEvent ) : boolean ;
149+ public dispatchEvent ( event : Event ) : boolean ;
132150 /**
133- * todo: what does the return boolean mean?
151+ * Dispatches an event to the registered event listeners.
152+ * Triggers callbacks registered via addEventListener with matching event types.
134153 *
135- * it returns false if the event is cancellable, and at least oneo the handlers which received event called
136- * Event.preventDefault(). Otherwise true.
137- * The use cases of preventDefault() does not apply to transfermanager but we should still keep the boolean
138- * and continue to return true to stay consistent with EventTarget.
154+ * @param event - The event object to dispatch.
155+ * @returns whether the event ran to completion
139156 *
157+ * @alpha
140158 */
141- public dispatchEvent ( event : Event & TransferEvent ) : boolean ;
142- public dispatchEvent ( event : Event & TransferCompleteEvent ) : boolean ;
143- public dispatchEvent ( event : Event ) : boolean ;
144159 public dispatchEvent ( event : Event ) : boolean {
145160 const eventType = event . type ;
146161 const listeners = this . eventListeners [ eventType as keyof TransferEventListeners ] as EventListener [ ] ;
@@ -182,6 +197,16 @@ export class S3TransferManager implements IS3TransferManager {
182197 callback : EventListener ,
183198 options ?: RemoveEventListenerOptions | boolean
184199 ) : void ;
200+ /**
201+ * Removes a previously registered event listener from the specified event type.
202+ * Stops the callback from being invoked when the event occurs.
203+ *
204+ * @param type - The type of event to stop listening for.
205+ * @param callback - The function that was previously registered.
206+ * @param options - Optional configuration for the event listener.
207+ *
208+ * @alpha
209+ */
185210 public removeEventListener (
186211 type : string ,
187212 callback : EventListener ,
@@ -209,10 +234,32 @@ export class S3TransferManager implements IS3TransferManager {
209234 }
210235 }
211236
237+ /**
238+ * Uploads objects to S3 with automatic multipart upload handling.
239+ * Automatically chooses between single object upload or multipart upload based on content length threshold.
240+ *
241+ * @param request - PutObjectCommandInput and CreateMultipartUploadCommandInput parameters for single or multipart uploads.
242+ * @param transferOptions - Optional abort signal and event listeners for transfer lifecycle monitoring.
243+ *
244+ * @returns S3 PutObject or CompleteMultipartUpload response with transfer event dispatching.
245+ *
246+ * @alpha
247+ */
212248 public upload ( request : UploadRequest , transferOptions ?: TransferOptions ) : Promise < UploadResponse > {
213249 throw new Error ( "Method not implemented." ) ;
214250 }
215251
252+ /**
253+ * Downloads single objects from S3 with automatic multipart handling.
254+ * Automatically chooses between PART or RANGE download strategies and joins streams into a single response.
255+ *
256+ * @param request - GetObjectCommandInput parameters. PartNumber is not supported - use GetObjectCommand directly for specific parts.
257+ * @param transferOptions - Optional abort signal and event listeners for transfer lifecycle monitoring.
258+ *
259+ * @returns S3 GetObject response with joined Body stream and transfer event dispatching.
260+ *
261+ * @alpha
262+ */
216263 public async download ( request : DownloadRequest , transferOptions ?: TransferOptions ) : Promise < DownloadResponse > {
217264 const partNumber = request . PartNumber ;
218265 if ( typeof partNumber === "number" ) {
@@ -248,12 +295,6 @@ export class S3TransferManager implements IS3TransferManager {
248295 }
249296 } ;
250297
251- // TODO:
252- // after completing SEP requirements:
253- // - acquire lock on webstreams in the same
254- // - synchronous frame as they are opened or else
255- // - the connection might be closed too early.
256-
257298 const response = {
258299 ...metadata ,
259300 Body : await joinStreams ( streams , {
@@ -299,6 +340,16 @@ export class S3TransferManager implements IS3TransferManager {
299340 return response ;
300341 }
301342
343+ /**
344+ * Uploads all files in a directory recursively to an S3 bucket.
345+ * Automatically maps local file paths to S3 object keys using prefix and delimiter configuration.
346+ *
347+ * @param options - Configuration including bucket, source directory, filtering, failure handling, and transfer settings.
348+ *
349+ * @returns the number of objects that have been uploaded and the number of objects that have failed
350+ *
351+ * @alpha
352+ */
302353 public uploadAll ( options : {
303354 bucket : string ;
304355 source : string ;
@@ -314,6 +365,16 @@ export class S3TransferManager implements IS3TransferManager {
314365 throw new Error ( "Method not implemented." ) ;
315366 }
316367
368+ /**
369+ * Downloads all objects in a bucket to a local directory.
370+ * Uses ListObjectsV2 to retrieve objects and automatically maps S3 object keys to local file paths.
371+ *
372+ * @param options - Configuration including bucket, destination directory, filtering, failure handling, and transfer settings.
373+ *
374+ * @returns The number of objects that have been downloaded and the number of objects that have failed
375+ *
376+ * @alpha
377+ */
317378 public downloadAll ( options : {
318379 bucket : string ;
319380 destination : string ;
@@ -328,6 +389,11 @@ export class S3TransferManager implements IS3TransferManager {
328389 throw new Error ( "Method not implemented." ) ;
329390 }
330391
392+ /**
393+ * Downloads object using part-based strategy with concurrent part requests.
394+ *
395+ * @internal
396+ */
331397 protected async downloadByPart (
332398 request : DownloadRequest ,
333399 transferOptions : TransferOptions ,
@@ -444,6 +510,11 @@ export class S3TransferManager implements IS3TransferManager {
444510 } ;
445511 }
446512
513+ /**
514+ * Downloads object using range-based strategy with concurrent range requests.
515+ *
516+ * @internal
517+ */
447518 protected async downloadByRange (
448519 request : DownloadRequest ,
449520 transferOptions : TransferOptions ,
@@ -589,6 +660,11 @@ export class S3TransferManager implements IS3TransferManager {
589660 } ;
590661 }
591662
663+ /**
664+ * Adds all event listeners from provided collection to the transfer manager.
665+ *
666+ * @internal
667+ */
592668 private addEventListeners ( eventListeners ?: TransferEventListeners ) : void {
593669 for ( const listeners of this . iterateListeners ( eventListeners ) ) {
594670 for ( const listener of listeners ) {
@@ -597,6 +673,11 @@ export class S3TransferManager implements IS3TransferManager {
597673 }
598674 }
599675
676+ /**
677+ * Removes event listeners from provided collection from the transfer manager.
678+ *
679+ * @internal
680+ */
600681 private removeEventListeners ( eventListeners ?: TransferEventListeners ) : void {
601682 for ( const listeners of this . iterateListeners ( eventListeners ) ) {
602683 for ( const listener of listeners ) {
@@ -605,6 +686,11 @@ export class S3TransferManager implements IS3TransferManager {
605686 }
606687 }
607688
689+ /**
690+ * Copies all response properties except Body to the container object.
691+ *
692+ * @internal
693+ */
608694 private assignMetadata ( container : any , response : any ) {
609695 for ( const key in response ) {
610696 if ( key === "Body" ) {
@@ -614,13 +700,23 @@ export class S3TransferManager implements IS3TransferManager {
614700 }
615701 }
616702
703+ /**
704+ * Updates response ContentLength and ContentRange based on total object size.
705+ *
706+ * @internal
707+ */
617708 private updateResponseLengthAndRange ( response : DownloadResponse , totalSize : number | undefined ) : void {
618709 if ( totalSize !== undefined ) {
619710 response . ContentLength = totalSize ;
620711 response . ContentRange = `bytes 0-${ totalSize - 1 } /${ totalSize } ` ;
621712 }
622713 }
623714
715+ /**
716+ * Clears checksum values for composite multipart downloads.
717+ *
718+ * @internal
719+ */
624720 private updateChecksumValues ( initialPart : DownloadResponse , metadata : Omit < DownloadResponse , "Body" > ) {
625721 if ( initialPart . ChecksumType === "COMPOSITE" ) {
626722 metadata . ChecksumCRC32 = undefined ;
@@ -630,6 +726,11 @@ export class S3TransferManager implements IS3TransferManager {
630726 }
631727 }
632728
729+ /**
730+ * Processes response metadata by updating length, copying properties, and handling checksums.
731+ *
732+ * @internal
733+ */
633734 private processResponseMetadata (
634735 response : DownloadResponse ,
635736 metadata : Omit < DownloadResponse , "Body" > ,
@@ -640,18 +741,33 @@ export class S3TransferManager implements IS3TransferManager {
640741 this . updateChecksumValues ( response , metadata ) ;
641742 }
642743
744+ /**
745+ * Throws AbortError if transfer has been aborted via signal.
746+ *
747+ * @internal
748+ */
643749 private checkAborted ( transferOptions ?: TransferOptions ) : void {
644750 if ( transferOptions ?. abortSignal ?. aborted ) {
645751 throw Object . assign ( new Error ( "Download aborted." ) , { name : "AbortError" } ) ;
646752 }
647753 }
648754
755+ /**
756+ * Validates configuration parameters meet minimum requirements.
757+ *
758+ * @internal
759+ */
649760 private validateConfig ( ) : void {
650761 if ( this . targetPartSizeBytes < S3TransferManager . MIN_PART_SIZE ) {
651762 throw new Error ( `targetPartSizeBytes must be at least ${ S3TransferManager . MIN_PART_SIZE } bytes` ) ;
652763 }
653764 }
654765
766+ /**
767+ * Dispatches transferInitiated event with initial progress snapshot.
768+ *
769+ * @internal
770+ */
655771 private dispatchTransferInitiatedEvent ( request : DownloadRequest | UploadRequest , totalSize ?: number ) : boolean {
656772 this . dispatchEvent (
657773 Object . assign ( new Event ( "transferInitiated" ) , {
@@ -665,6 +781,11 @@ export class S3TransferManager implements IS3TransferManager {
665781 return true ;
666782 }
667783
784+ /**
785+ * Dispatches transferFailed event with error details and progress snapshot.
786+ *
787+ * @internal
788+ */
668789 private dispatchTransferFailedEvent (
669790 request : DownloadRequest | UploadRequest ,
670791 totalSize ?: number ,
@@ -683,6 +804,11 @@ export class S3TransferManager implements IS3TransferManager {
683804 return true ;
684805 }
685806
807+ /**
808+ * Generator that yields event listeners from the provided collection for iteration.
809+ *
810+ * @internal
811+ */
686812 private * iterateListeners ( eventListeners : TransferEventListeners = { } ) {
687813 for ( const key in eventListeners ) {
688814 const eventType = key as keyof TransferEventListeners ;
@@ -700,6 +826,11 @@ export class S3TransferManager implements IS3TransferManager {
700826 }
701827 }
702828
829+ /**
830+ * Validates part download ContentRange matches expected part boundaries.
831+ *
832+ * @internal
833+ */
703834 private validatePartDownload ( contentRange : string | undefined , partNumber : number , partSize : number ) {
704835 if ( ! contentRange ) {
705836 throw new Error ( `Missing ContentRange for part ${ partNumber } .` ) ;
@@ -724,6 +855,11 @@ export class S3TransferManager implements IS3TransferManager {
724855 }
725856 }
726857
858+ /**
859+ * Validates range download ContentRange matches requested byte range.
860+ *
861+ * @internal
862+ */
727863 private validateRangeDownload ( requestRange : string , responseRange : string | undefined ) {
728864 if ( ! responseRange ) {
729865 throw new Error ( `Missing ContentRange for range ${ requestRange } .` ) ;
@@ -757,8 +893,9 @@ export class S3TransferManager implements IS3TransferManager {
757893 throw new Error ( `Expected range to end at ${ expectedEnd } but got ${ end } ` ) ;
758894 }
759895}
896+
760897/**
761- *
898+ * Internal event handler for download lifecycle hooks.
762899 *
763900 * @internal
764901 */
0 commit comments