UNPKG

@jrmc/adonis-attachment

Version:

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

122 lines (121 loc) 3.82 kB
/** * @jrmc/adonis-attachment * * @license MIT * @copyright Jeremy Chaufourier <jeremy@chaufourier.fr> */ import os from 'node:os'; import path from 'node:path'; import https from 'node:https'; import fs from 'node:fs/promises'; import { pipeline } from 'node:stream'; import { promisify } from 'node:util'; import { createWriteStream } from 'node:fs'; import BlurhashAdapter from '../adapters/blurhash.js'; import * as errors from '../errors.js'; const streamPipeline = promisify(pipeline); export function cleanObject(obj) { if (obj === null || typeof obj !== 'object') { return obj; } const cleanedObj = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const cleanedValue = cleanObject(obj[key]); if (cleanedValue !== null && cleanedValue !== undefined && cleanedValue !== 0 && cleanedValue !== '') { cleanedObj[key] = cleanedValue; } } } return cleanedObj; } export async function use(module) { try { const result = await import(module); if (result.default) { return result.default; } return result; } catch (err) { throw new errors.E_MISSING_PACKAGE([module], { cause: err }); } } export async function bufferToTempFile(input) { const folder = os.tmpdir(); const tempFilePath = path.join(folder, `tempfile-${Date.now()}.tmp`); await fs.writeFile(tempFilePath, input); return tempFilePath; } export async function streamToTempFile(input) { const folder = os.tmpdir(); const tempFilePath = path.join(folder, `tempfile-${Date.now()}.tmp`); const writeStream = createWriteStream(tempFilePath); try { await streamPipeline(input, writeStream); return tempFilePath; } catch (err) { throw new errors.E_CANNOT_GENERATE_TEMP_FILE([err.message]); } } export async function downloadToTempFile(input) { return await new Promise((resolve) => { https .get(input, (response) => { if (response.statusCode === 200) { resolve(streamToTempFile(response)); } else { // reject(`${response.statusCode}`) throw new errors.E_CANNOT_GENERATE_TEMP_FILE(['']); } }) .on('error', (err) => { throw new errors.E_CANNOT_GENERATE_TEMP_FILE([err.message]); }); }); } export function isBase64(str) { const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/; if (!base64Regex.test(str)) { return false; } try { Buffer.from(str, 'base64').toString(); return true; } catch (err) { return false; } } export function imageToBlurhash(input, options) { const { componentX, componentY } = options || { componentX: 4, componentY: 4 }; return new Promise(async (resolve, reject) => { try { const sharp = await use('sharp'); // Convert input to pixels const { data: pixels, info: metadata } = await sharp(input) .raw() .ensureAlpha() .toBuffer({ resolveWithObject: true }); const blurhash = BlurhashAdapter.encode(new Uint8ClampedArray(pixels), metadata.width, metadata.height, componentX, componentY); return resolve(blurhash); } catch (error) { return reject(error); } }); } export function extractPathParameters(path) { const paramRegex = /:(\w+)/g; const parameters = []; let match; while ((match = paramRegex.exec(path)) !== null) { parameters.push(match[1]); } return parameters; }