UNPKG

@jrmc/adonis-attachment

Version:

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

120 lines (119 loc) 4.56 kB
import logger from '@adonisjs/core/services/logger'; import string from '@adonisjs/core/helpers/string'; import db from '@adonisjs/lucid/services/db'; import attachmentManager from '../services/main.js'; import * as errors from './errors.js'; import { streamToTempFile } from './utils/helpers.js'; export class ConverterManager { #record; #attributeName; #options; #filters; constructor({ record, attributeName, options, filters }) { this.#record = record; this.#attributeName = attributeName; this.#options = options; this.#filters = filters; } async run() { const attachments = this.#record.getAttachments({ attributeName: this.#attributeName, }); const variants = []; await this.#purge(attachments); if (!attachments || !this.#options.variants || !this.#options.variants.length) { return; } for await (const key of this.#options.variants) { if (this.#filters?.variants !== undefined && !this.#filters?.variants?.includes(key)) { continue; } const converter = (await attachmentManager.getConverter(key)); if (converter) { for await (const attachment of attachments) { const variant = await this.#generate({ key, attachment, converter }); variants.push(variant); } } } return this.#commit(attachments, () => { for (let i = 0; i < variants.length; i++) { attachmentManager.remove(variants[i]); } }); } async #generate({ key, attachment, converter }) { let input = attachment.input; if (!input) { input = await streamToTempFile(await attachment.getStream()); } const output = await converter.handle({ input, options: converter.options, }); if (output === undefined) { throw new errors.E_CANNOT_PATH_BY_CONVERTER(); } const variant = await attachment.createVariant(key, output); if (converter.options.blurhash) { if ((typeof converter.options.blurhash !== 'boolean' && converter.options.blurhash.enabled === true) || converter.options.blurhash === true) { try { const options = typeof converter.options.blurhash !== 'boolean' ? converter.options.blurhash : undefined; await variant.generateBlurhash(options); } catch (error) { logger.error(error.message); } } } await attachmentManager.write(variant); return variant; } async #commit(attachments, rollback) { const Model = this.#record.row.constructor; const id = this.#record.row.$attributes['id']; const data = {}; const index = string.snakeCase(this.#attributeName); if (Array.isArray(this.#record.row.$original[this.#attributeName])) { data[index] = JSON.stringify(attachments.map((att) => att.toObject())); } else { data[index] = JSON.stringify(attachments[0].toObject()); } const trx = await db.transaction(); trx.after('rollback', rollback); try { await trx.query().from(Model.table).where('id', id).update(data); return trx.commit(); } catch (error) { return trx.rollback(); } } async #purge(attachments) { return Promise.all(attachments.map(async (attachment) => { if (attachment.variants?.length) { await Promise.all(attachment.variants.map(async (variant) => { if (this.#filters?.variants !== undefined && !this.#filters?.variants?.includes(variant.key)) { return; } return attachmentManager.remove(variant); })); if (this.#filters?.variants !== undefined) { attachment.variants = await attachment.variants.filter((variant) => !this.#filters?.variants?.includes(variant.key)); } else { attachment.variants = []; } } })); } }