mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
72 lines
1.7 KiB
TypeScript
72 lines
1.7 KiB
TypeScript
import fetch from 'node-fetch'
|
|
import sharp from 'sharp'
|
|
|
|
/**
|
|
* This module was inspired by Zach Leatherman's `avatar-local-cache` library.
|
|
* Check out https://github.com/zachleat/avatar-local-cache for a similar,
|
|
* pre-packaged solution.
|
|
*/
|
|
|
|
export interface AvatarCacheOptions {
|
|
/** The path to write the images to. */
|
|
outputDirectory: string
|
|
/** The max width of the avatars. */
|
|
width?: number
|
|
}
|
|
|
|
export class AvatarCache {
|
|
outputDirectory: string
|
|
width: number
|
|
|
|
constructor({ outputDirectory, width = 120 }: AvatarCacheOptions) {
|
|
this.outputDirectory = outputDirectory
|
|
this.width = width
|
|
}
|
|
|
|
async urlToFile(url: string, outputFileSlug: string) {
|
|
try {
|
|
const response = await fetch(url)
|
|
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Bad status code for ${url}. ${response.status}: ${response.statusText}`,
|
|
)
|
|
}
|
|
|
|
const body = await response.arrayBuffer()
|
|
|
|
return this.processImage(body, outputFileSlug)
|
|
} catch (error) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(`Error processing ${url}\nError: ${error}`)
|
|
}
|
|
}
|
|
|
|
private async processImage(body: ArrayBuffer, outputFileSlug: string) {
|
|
const { width, outputDirectory } = this
|
|
const output = `${outputDirectory}/${outputFileSlug}`
|
|
|
|
const img = sharp(Buffer.from(body)).resize({
|
|
width: width,
|
|
withoutEnlargement: true,
|
|
})
|
|
const metadata = await img.metadata()
|
|
|
|
await this.toJpeg(img, metadata, `${output}.jpg`)
|
|
|
|
return `${outputFileSlug}.jpg`
|
|
}
|
|
|
|
private async toJpeg(
|
|
img: sharp.Sharp,
|
|
metadata: sharp.Metadata,
|
|
slug: string,
|
|
) {
|
|
const jpeg = metadata.format !== 'jpeg' ? img.jpeg() : img
|
|
|
|
await jpeg.toFile(slug)
|
|
}
|
|
}
|
|
|
|
export default AvatarCache
|