import { detectPdf } from '@file-type/pdf'; import { type AxiosInstance } from 'axios'; import { isNonEmptyString } from '@sniptt/guards'; import { FileTypeParser } from 'file-type'; import { isDefined } from 'twenty-shared/utils'; export const getImageBufferFromUrl = async ( url: string, axiosInstance: AxiosInstance, ): Promise => { if (!isNonEmptyString(url) || url.trim().length === 0) { throw new Error('Invalid URL provided: URL must be a non-empty string'); } try { const response = await axiosInstance.get(url, { responseType: 'arraybuffer', validateStatus: (status) => status >= 200 && status < 300, maxRedirects: 5, timeout: 10000, }); if (!response.data) { throw new Error('Received empty response from image URL'); } const bufferLength = Buffer.isBuffer(response.data) ? response.data.length : response.data.byteLength; if (bufferLength === 0) { throw new Error('Received empty response from image URL'); } const contentType = response.headers['content-type']; if (isNonEmptyString(contentType) && !contentType.startsWith('image/')) { throw new Error( `Invalid content type: expected image/*, got ${contentType}`, ); } return Buffer.from(response.data, 'binary'); } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to fetch image from ${url}: ${message}`); } }; export const fetchImageWithTypeFromUrl = async ( imageUrl: string, axiosInstance: AxiosInstance, ): Promise<{ buffer: Buffer; extension: string } | undefined> => { const buffer = await getImageBufferFromUrl(imageUrl, axiosInstance); const parser = new FileTypeParser({ customDetectors: [detectPdf] }); const type = await parser.fromBuffer(buffer); if (!isDefined(type) || !type.mime.startsWith('image/')) { return undefined; } return { buffer, extension: type.ext }; };