Skip to content

Commit 296f4b1

Browse files
authored
feat: format option for webp support (#142)
1 parent 307644a commit 296f4b1

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

infra/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,6 @@ services:
8484
environment:
8585
- IMGPROXY_LOCAL_FILESYSTEM_ROOT=/
8686
- IMGPROXY_USE_ETAG=true
87+
- IMGPROXY_ENABLE_WEBP_DETECTION=true
8788
volumes:
8889
assets-volume:

infra/storage/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM supabase/storage-api:v0.25.1
1+
FROM supabase/storage-api:v0.27.1
22

33
RUN apk add curl --no-cache

src/lib/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,11 @@ export interface TransformOptions {
8989
* Fill resizes the image to fill the entire width and height. If the object's aspect ratio does not match the width and height, the image will be stretched to fit.
9090
*/
9191
resize?: 'cover' | 'contain' | 'fill'
92+
/**
93+
* Specify the format of the image requested.
94+
*
95+
* When using 'origin' we force the format to be the same as the original image,
96+
* bypassing automatic browser optimisation such as webp conversion
97+
*/
98+
format?: 'origin'
9299
}

src/packages/StorageFileApi.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,10 @@ export default class StorageFileApi {
593593
params.push(`resize=${transform.resize}`)
594594
}
595595

596+
if (transform.format) {
597+
params.push(`format=${transform.format}`)
598+
}
599+
596600
return params.join('&')
597601
}
598602
}

test/storageFileApi.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,47 @@ describe('Object API', () => {
248248
})
249249
})
250250

251+
it('will return the image as webp when the browser support it', async () => {
252+
const storage = new StorageClient(URL, { Authorization: `Bearer ${KEY}`, Accept: 'image/webp' })
253+
const privateBucketName = 'my-private-bucket'
254+
await findOrCreateBucket(privateBucketName)
255+
256+
const { error: uploadError } = await storage.from(privateBucketName).upload(uploadPath, file)
257+
expect(uploadError).toBeNull()
258+
259+
const res = await storage.from(privateBucketName).download(uploadPath, {
260+
transform: {
261+
width: 200,
262+
height: 200,
263+
},
264+
})
265+
266+
expect(res.error).toBeNull()
267+
expect(res.data?.size).toBeGreaterThan(0)
268+
expect(res.data?.type).toEqual('image/webp')
269+
})
270+
271+
it('will return the original image format when format is origin', async () => {
272+
const storage = new StorageClient(URL, { Authorization: `Bearer ${KEY}`, Accept: 'image/webp' })
273+
const privateBucketName = 'my-private-bucket'
274+
await findOrCreateBucket(privateBucketName)
275+
276+
const { error: uploadError } = await storage.from(privateBucketName).upload(uploadPath, file)
277+
expect(uploadError).toBeNull()
278+
279+
const res = await storage.from(privateBucketName).download(uploadPath, {
280+
transform: {
281+
width: 200,
282+
height: 200,
283+
format: 'origin',
284+
},
285+
})
286+
287+
expect(res.error).toBeNull()
288+
expect(res.data?.size).toBeGreaterThan(0)
289+
expect(res.data?.type).toEqual('image/jpeg')
290+
})
291+
251292
it('will get a signed transformed image', async () => {
252293
await storage.from(bucketName).upload(uploadPath, file)
253294
const res = await storage.from(bucketName).createSignedUrl(uploadPath, 60000, {

0 commit comments

Comments
 (0)