UNPKG

@jrmc/adonis-attachment

Version:

Turn any field on your Lucid model to an attachment data type

102 lines (101 loc) 3.88 kB
/** * @jrmc/adonis-attachment * * @license MIT * @copyright Jeremy Chaufourier <jeremy@chaufourier.fr> */ import app from '@adonisjs/core/services/app'; import logger from '@adonisjs/core/services/logger'; import { streamToTempFile } from '../../utils/helpers.js'; export default class VariantGeneratorService { async #getAttachmentManager() { return app.container.make('jrmc.attachment'); } async generate({ attachments, options, filters, }) { const variants = []; const variantKeys = this.#getVariantKeysToProcess(options, filters); for (const key of variantKeys) { const converter = await this.#getConverter(key); if (!converter) continue; for (const attachment of attachments) { const variant = await this.generateVariant({ key, attachment, converter }); if (variant) { variants.push(variant); } } } return variants; } async generateVariant({ key, attachment, converter, }) { try { const attachmentManager = await this.#getAttachmentManager(); const input = await this.#prepareInput(attachment); const output = await this.#convertFile(input, converter); if (!output) { // throw new errors.E_CANNOT_PATH_BY_CONVERTER() logger.warn(`Converter returned no output for key: ${key}`); return null; } const basePath = attachmentManager.getConfig().variant?.basePath; const ignoreFolder = attachmentManager.getConfig().variant?.ignoreFolder; const variant = await attachment.createVariant(key, output, { basePath, ignoreFolder }); await this.#processBlurhash(variant, converter); await attachmentManager.write(variant); return variant; } catch (error) { logger.error(`Failed to generate variant ${key} for attachment: ${error.message}`); return null; } } #getVariantKeysToProcess(options, filters) { if (!options.variants) return []; return options.variants.filter((key) => filters?.variants === undefined || filters.variants.includes(key)); } async #getConverter(key) { try { const attachmentManager = await this.#getAttachmentManager(); return (await attachmentManager.getConverter(key)); } catch (error) { logger.error(`Failed to get converter for key ${key}: ${error.message}`); return null; } } async #prepareInput(attachment) { if (attachment.input) { return attachment.input; } const stream = await attachment.getStream(); return await streamToTempFile(stream); } async #convertFile(input, converter) { if (!converter.handle) { throw new Error('Converter handle method is required'); } if (!converter.options) { throw new Error('Converter options are required'); } return await converter.handle({ input, options: converter.options, }); } async #processBlurhash(variant, converter) { const blurhashConfig = converter.options?.blurhash; if (!blurhashConfig) return; const shouldGenerate = typeof blurhashConfig === 'boolean' ? blurhashConfig : blurhashConfig.enabled === true; if (!shouldGenerate) return; try { const options = typeof blurhashConfig !== 'boolean' ? blurhashConfig : undefined; await variant.generateBlurhash(options); } catch (error) { logger.error(`Blurhash generation failed: ${error.message}`); } } }