@@ -39,6 +39,7 @@ import {
3939 type CreateAttachmentParams ,
4040} from "../services/hypercerts/types.js" ;
4141import type {
42+ BlobOperations ,
4243 LocationParams ,
4344 CreateHypercertParams ,
4445 CreateHypercertResult ,
@@ -106,15 +107,15 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
106107 *
107108 * @param agent - AT Protocol Agent for making API calls
108109 * @param repoDid - DID of the repository to operate on
109- * @param _serverUrl - Server URL (reserved for future use)
110+ * @param blobs - Blob operations for uploading images and files
110111 * @param logger - Optional logger for debugging
111112 *
112113 * @internal
113114 */
114115 constructor (
115116 private agent : Agent ,
116117 private repoDid : string ,
117- private _serverUrl : string ,
118+ private blobs : BlobOperations ,
118119 private logger ?: LoggerInterface ,
119120 ) {
120121 super ( ) ;
@@ -138,25 +139,19 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
138139 }
139140
140141 /**
141- * Helper function to upload a blob to the repository, returns a blob reference
142+ * Converts a blob upload result to JsonBlobRef format.
142143 *
143- * @param content - Blob to upload
144- * @param fallbackContentType | if content.type is empty,we use this
145- * @returns BlobRef
146- * @throws {@link NetworkError } if upload fails
144+ * @param uploadResult - Result from BlobOperations.upload()
145+ * @returns JsonBlobRef formatted for records
147146 * @internal
148147 */
149-
150- private async handleBlobUpload ( content : Blob , fallbackContentType : string ) {
151- const arrayBuffer = await content . arrayBuffer ( ) ;
152- const uint8Array = new Uint8Array ( arrayBuffer ) ;
153- const uploadResult = await this . agent . com . atproto . repo . uploadBlob ( uint8Array , {
154- encoding : content . type || fallbackContentType ,
155- } ) ;
156- if ( ! uploadResult . success ) {
157- throw new NetworkError ( "Failed to upload blob" ) ;
158- }
159- return uploadResult . data . blob ;
148+ private blobToJsonRef ( uploadResult : { ref : { $link : string } ; mimeType : string ; size : number } ) : JsonBlobRef {
149+ return {
150+ $type : "blob" ,
151+ ref : uploadResult . ref ,
152+ mimeType : uploadResult . mimeType ,
153+ size : uploadResult . size ,
154+ } ;
160155 }
161156
162157 /**
@@ -174,26 +169,13 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
174169 ) : Promise < JsonBlobRef | undefined > {
175170 this . emitProgress ( onProgress , { name : "uploadImage" , status : "start" } ) ;
176171 try {
177- const arrayBuffer = await image . arrayBuffer ( ) ;
178- const uint8Array = new Uint8Array ( arrayBuffer ) ;
179- const uploadResult = await this . agent . com . atproto . repo . uploadBlob ( uint8Array , {
180- encoding : image . type || "image/jpeg" ,
172+ const uploadResult = await this . blobs . upload ( image ) ;
173+ this . emitProgress ( onProgress , {
174+ name : "uploadImage" ,
175+ status : "success" ,
176+ data : { size : image . size } ,
181177 } ) ;
182- if ( uploadResult . success ) {
183- const blobRef : JsonBlobRef = {
184- $type : "blob" ,
185- ref : { $link : uploadResult . data . blob . ref . toString ( ) } ,
186- mimeType : uploadResult . data . blob . mimeType ,
187- size : uploadResult . data . blob . size ,
188- } ;
189- this . emitProgress ( onProgress , {
190- name : "uploadImage" ,
191- status : "success" ,
192- data : { size : image . size } ,
193- } ) ;
194- return blobRef ;
195- }
196- throw new NetworkError ( "Image upload succeeded but returned no blob reference" ) ;
178+ return this . blobToJsonRef ( uploadResult ) ;
197179 } catch ( error ) {
198180 this . emitProgress ( onProgress , { name : "uploadImage" , status : "error" , error : error as Error } ) ;
199181 throw new NetworkError ( `Failed to upload image: ${ error instanceof Error ? error . message : "Unknown" } ` , error ) ;
@@ -723,19 +705,8 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
723705 if ( params . image === null ) {
724706 // Remove image
725707 } else {
726- const arrayBuffer = await params . image . arrayBuffer ( ) ;
727- const uint8Array = new Uint8Array ( arrayBuffer ) ;
728- const uploadResult = await this . agent . com . atproto . repo . uploadBlob ( uint8Array , {
729- encoding : params . image . type || "image/jpeg" ,
730- } ) ;
731- if ( uploadResult . success ) {
732- recordForUpdate . image = {
733- $type : "blob" ,
734- ref : uploadResult . data . blob . ref ,
735- mimeType : uploadResult . data . blob . mimeType ,
736- size : uploadResult . data . blob . size ,
737- } ;
738- }
708+ const uploadResult = await this . blobs . upload ( params . image ) ;
709+ recordForUpdate . image = this . blobToJsonRef ( uploadResult ) ;
739710 }
740711 } else if ( existingRecord . image ) {
741712 // Preserve existing image
@@ -980,7 +951,7 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
980951 * @returns Promise resolving to either a URI ref or blob ref
981952 * @internal
982953 */
983- private async resolveUriOrBlob ( content : string | Blob , fallbackMimeType : string ) {
954+ private async resolveUriOrBlob ( content : string | Blob , _fallbackMimeType : string ) {
984955 if ( typeof content === "string" ) {
985956 const uriRef = {
986957 $type : "org.hypercerts.defs#uri" ,
@@ -989,12 +960,11 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
989960 return uriRef ;
990961 }
991962
992- const uploadedBlob = await this . handleBlobUpload ( content , fallbackMimeType ) ;
993- const blobRef = {
994- $type : "org.hypercerts.defs#smallBlob" ,
995- blob : uploadedBlob ,
996- } satisfies $Typed < OrgHypercertsDefs . SmallBlob > ;
997- return blobRef ;
963+ const uploadResult = await this . blobs . upload ( content ) ;
964+ return {
965+ $type : "org.hypercerts.defs#smallBlob" as const ,
966+ blob : uploadResult ,
967+ } ;
998968 }
999969
1000970 private async resolveCollectionImageInput ( input : string | Blob ) : Promise < NonNullable < HypercertCollection [ "avatar" ] > > ;
@@ -1007,12 +977,12 @@ export class HypercertOperationsImpl extends EventEmitter<HypercertEvents> imple
1007977 return { $type : "org.hypercerts.defs#uri" as const , uri : input } ;
1008978 }
1009979
1010- const blob = await this . handleBlobUpload ( input , "image/jpeg" ) ;
980+ const uploadResult = await this . blobs . upload ( input ) ;
1011981 if ( isBanner ) {
1012- return { $type : "org.hypercerts.defs#largeImage" as const , image : blob } ;
982+ return { $type : "org.hypercerts.defs#largeImage" as const , image : uploadResult } ;
1013983 }
1014984
1015- return { $type : "org.hypercerts.defs#smallImage" as const , image : blob } ;
985+ return { $type : "org.hypercerts.defs#smallImage" as const , image : uploadResult } ;
1016986 }
1017987
1018988 private async resolveLocationValue ( location : string | Blob | HypercertLocation [ "location" ] ) {
0 commit comments