@jrmc/adonis-attachment
Version:
Turn any field on your Lucid model to an attachment data type
122 lines (121 loc) • 3.82 kB
JavaScript
/**
* @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;
}