UNPKG

@jrmc/adonis-attachment

Version:

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

105 lines (104 loc) 4.33 kB
import path from 'node:path'; import { Readable } from 'node:stream'; import encryption from '@adonisjs/core/services/encryption'; import db from '@adonisjs/lucid/services/db'; import { attachmentManager } from '@jrmc/adonis-attachment'; import VariantGeneratorService from '../services/variant/variant_generator_service.js'; import VariantPersisterService from '../services/variant/variant_persister_service.js'; export default class AttachmentsController { async handle({ request, response }) { const { key } = request.params(); const format = request.qs()?.variant; let multiple = false; const data = encryption.decrypt(key); await attachmentManager.lock.createLock(`attachment.${data.model}-${data.attribute}`).run(async () => { const queryWithTableSelection = await db .from(data.model) .select(data.attribute) .where(data.primaryKey, data.id).first(); /* * 1. Get the Attachment(s) */ const result = typeof queryWithTableSelection[data.attribute] === 'string' ? JSON.parse(queryWithTableSelection[data.attribute]) : queryWithTableSelection[data.attribute]; const attachments = []; let currentAttachment = null; if (Array.isArray(result)) { multiple = true; for (const item of result) { item.folder = path.dirname(item.path); const attachment = attachmentManager.createFromDbResponse(item); if (attachment) { attachment.setOptions(data.options); attachments.push(attachment); } } currentAttachment = attachments[data.index || 0]; } else { result.folder = path.dirname(result.path); currentAttachment = attachmentManager.createFromDbResponse(result); if (currentAttachment) { currentAttachment.setOptions(data.options); } } if (!currentAttachment) { return response.notFound(); } /* * 2. Get the variant */ let variant = currentAttachment.getVariant(format); /* * 3. Get the stream * if variant and path, get the stream and return it * if not, generate the variant * if not, return the default file */ if (!variant && format) { const converter = (await attachmentManager.getConverter(format)); variant = await (new VariantGeneratorService()).generateVariant({ key: format, attachment: currentAttachment, converter }); if (variant) { const variantPersister = new VariantPersisterService({ id: data.id, modelTable: data.model, attributeName: data.attribute, multiple, primaryKey: data.primaryKey }); const attachmentsOrCurrent = attachments.length ? attachments : [currentAttachment]; await variantPersister.persist({ attachments: attachmentsOrCurrent, variants: [variant] }); } } /* * 5. Get the stream */ let stream; let mimeType; if (variant) { stream = await variant.getStream(); mimeType = variant.mimeType; } else if (currentAttachment) { stream = await currentAttachment.getStream(); mimeType = currentAttachment.mimeType; } /* * 6. Return the stream */ if (stream && mimeType) { const readable = Readable.from(stream); response.header('Content-Type', mimeType); response.stream(readable); } else { return response.notFound(); } }); } }