diff --git a/.changeset/moody-ties-explode.md b/.changeset/moody-ties-explode.md new file mode 100644 index 00000000000..ce84f81d032 --- /dev/null +++ b/.changeset/moody-ties-explode.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/storage": patch +--- + +Replace schemes after files are uploaded diff --git a/packages/storage/src/core/storage.ts b/packages/storage/src/core/storage.ts index 0b7ec7d06bd..99025097797 100644 --- a/packages/storage/src/core/storage.ts +++ b/packages/storage/src/core/storage.ts @@ -199,35 +199,32 @@ export class ThirdwebStorage { options?: T, ): Promise { let cleaned = data; - // TODO: Gateway URLs should probably be top-level since both uploader and downloader need them - if (this.gatewayUrls) { - // Replace any gateway URLs with their hashes - cleaned = replaceObjectGatewayUrlsWithSchemes( - cleaned, - this.gatewayUrls, - ) as Json[]; - - if (options?.uploadWithGatewayUrl || this.uploader.uploadWithGatewayUrl) { - // If flag is set, replace all schemes with their preferred gateway URL - // Ex: used for Solana, where services don't resolve schemes for you, so URLs must be useable by default - cleaned = replaceObjectSchemesWithGatewayUrls( - cleaned, - this.gatewayUrls, - ) as Json[]; - } - } + // Replace any gateway URLs with their hashes + cleaned = replaceObjectGatewayUrlsWithSchemes( + cleaned, + this.gatewayUrls, + ) as Json[]; // Recurse through data and extract files to upload const files = extractObjectFiles(cleaned); - if (!files.length) { - return cleaned; + if (files.length) { + // Upload all files that came from the object + const uris = await this.uploader.uploadBatch(files); + + // Recurse through data and replace files with hashes + cleaned = replaceObjectFilesWithUris(cleaned, uris) as Json[]; } - // Upload all files that came from the object - const uris = await this.uploader.uploadBatch(files); + if (options?.uploadWithGatewayUrl || this.uploader.uploadWithGatewayUrl) { + // If flag is set, replace all schemes with their preferred gateway URL + // Ex: used for Solana, where services don't resolve schemes for you, so URLs must be useable by default + cleaned = replaceObjectSchemesWithGatewayUrls( + cleaned, + this.gatewayUrls, + ) as Json[]; + } - // Recurse through data and replace files with hashes - return replaceObjectFilesWithUris(cleaned, uris) as Json[]; + return cleaned; } } diff --git a/packages/storage/test/images/0.jpg b/packages/storage/test/images/0.jpg new file mode 100644 index 00000000000..a9bf6dda5a7 Binary files /dev/null and b/packages/storage/test/images/0.jpg differ diff --git a/packages/storage/test/images/1.jpg b/packages/storage/test/images/1.jpg new file mode 100644 index 00000000000..55473d72620 Binary files /dev/null and b/packages/storage/test/images/1.jpg differ diff --git a/packages/storage/test/images/2.jpg b/packages/storage/test/images/2.jpg new file mode 100644 index 00000000000..243863730c3 Binary files /dev/null and b/packages/storage/test/images/2.jpg differ diff --git a/packages/storage/test/images/3.jpg b/packages/storage/test/images/3.jpg new file mode 100644 index 00000000000..8d2ef936b90 Binary files /dev/null and b/packages/storage/test/images/3.jpg differ diff --git a/packages/storage/test/images/4.jpg b/packages/storage/test/images/4.jpg new file mode 100644 index 00000000000..affbf45284b Binary files /dev/null and b/packages/storage/test/images/4.jpg differ diff --git a/packages/storage/test/images/5.jpg b/packages/storage/test/images/5.jpg new file mode 100644 index 00000000000..74f0d54fd9f Binary files /dev/null and b/packages/storage/test/images/5.jpg differ diff --git a/packages/storage/test/ipfs.test.ts b/packages/storage/test/ipfs.test.ts index f1d6fb1416d..0d922602bb5 100644 --- a/packages/storage/test/ipfs.test.ts +++ b/packages/storage/test/ipfs.test.ts @@ -199,31 +199,6 @@ describe("IPFS", async () => { expect(json.description).to.equal("Uploading alone without a directory..."); }); - it("Should upload without directory if specified on class", async () => { - const solanaStorage = new ThirdwebStorage({ - uploader: new IpfsUploader({ uploadWithGatewayUrl: true }), - }); - - const uri = await solanaStorage.upload( - { - name: "Upload Without Directory", - description: "Uploading alone without a directory...", - }, - { - uploadWithoutDirectory: true, - }, - ); - - expect(uri).to.equal( - "ipfs://QmdnBEP9UFcRfbuAyXFefNccNbuKWTscHrpWZatvqz9VcV", - ); - - const json = await storage.downloadJSON(uri); - - expect(json.name).to.equal("Upload Without Directory"); - expect(json.description).to.equal("Uploading alone without a directory..."); - }); - it("Should throw an error on upload without directory with multiple uploads", async () => { try { await storage.uploadBatch( @@ -267,7 +242,28 @@ describe("IPFS", async () => { ); }); - it("Should upload files with gateway URLs if specified", async () => { + it("Should upload files with gateway URLs if specified on class", async () => { + const uploader = new IpfsUploader({ uploadWithGatewayUrl: true }); + const singleStorage = new ThirdwebStorage({ uploader }); + + const uri = await singleStorage.upload({ + // Gateway URLs should first be converted back to ipfs:// and then all ipfs:// should convert to first gateway URL + image: readFileSync("test/images/0.jpg"), + animation_url: "ipfs://QmbaNzUcv7KPgdwq9u2qegcptktpUK6CdRZF72eSjSa6iJ/0", + }); + + const res = await singleStorage.download(uri); + const json = await res.json(); + + expect(json.image).to.equal( + `${DEFAULT_GATEWAY_URLS["ipfs://"][0]}QmcCJC4T37rykDjR6oorM8hpB9GQWHKWbAi2YR1uTabUZu/0`, + ); + expect(json.animation_url).to.equal( + `${DEFAULT_GATEWAY_URLS["ipfs://"][0]}QmbaNzUcv7KPgdwq9u2qegcptktpUK6CdRZF72eSjSa6iJ/0`, + ); + }); + + it("Should upload files with gateway URLs if specified on function", async () => { const uri = await storage.upload( { // Gateway URLs should first be converted back to ipfs:// and then all ipfs:// should convert to first gateway URL