@jrmc/adonis-attachment
Version:
Turn any field on your Lucid model to an attachment data type
204 lines (203 loc) • 5.89 kB
JavaScript
/**
* @jrmc/adonis-attachment
*
* @license MIT
* @copyright Jeremy Chaufourier <jeremy@chaufourier.fr>
*/
import string from '@adonisjs/core/helpers/string';
import path from 'node:path';
import { cuid } from '@adonisjs/core/helpers';
import { defaultOptionsDecorator } from '../utils/default_values.js';
import { extractPathParameters } from '../utils/helpers.js';
export class AttachmentBase {
drive;
input;
#keyId;
#name;
#folder;
size;
extname;
mimeType;
meta;
originalPath;
url;
options;
constructor(drive, attributes, input) {
this.input = input;
this.size = attributes.size;
this.meta = attributes.meta;
this.extname = attributes.extname;
this.mimeType = attributes.mimeType;
this.originalPath = attributes.path;
this.#folder = attributes.folder;
this.setOptions({ folder: attributes.folder });
if (attributes.name) {
this.#name = attributes.name;
}
else {
this.#name = `${cuid()}.${this.extname}`;
}
this.options = defaultOptionsDecorator;
this.drive = drive;
}
/**
* Getters / Setters
*/
get name() {
return this.#name;
}
set name(name) {
this.#name = name;
}
get folder() {
if (this.#folder) {
return this.#folder;
}
if (typeof this.options.folder === 'string') {
const parameters = extractPathParameters(this.options.folder);
if (!parameters.length) {
return this.options.folder;
}
}
}
get path() {
if (!this.folder && this.originalPath) {
return this.originalPath;
}
return path.join(this.folder, this.name);
}
/**
* Methods
*/
getDisk() {
return this.drive.use(this.options?.disk);
}
getBytes() {
return this.getDisk().getBytes(this.path);
}
async getBuffer() {
const arrayBuffer = await this.getBytes();
return Buffer.from(arrayBuffer);
}
getStream() {
return this.getDisk().getStream(this.path);
}
getUrl() {
return this.getDisk().getUrl(this.path);
}
getSignedUrl(signedUrlOptions) {
return this.getDisk().getSignedUrl(this.path, signedUrlOptions);
}
getKeyId() {
return this.#keyId;
}
setKeyId(keyId) {
this.#keyId = keyId;
return this;
}
setOptions(options) {
this.options = {
...this.options,
...options,
};
return this;
}
/**
* Actions
*/
async computeUrl(signedUrlOptions) {
const disk = this.getDisk();
const fileVisibility = await disk.getVisibility(this.path);
if (fileVisibility === 'private') {
this.url = await this.getSignedUrl(signedUrlOptions);
}
else {
this.url = await this.getUrl();
}
}
async preComputeUrl() {
if (this.options?.preComputeUrl === false) {
return;
}
await this.computeUrl();
}
async makeName(record, attributeName, originalName) {
if (typeof this.options.rename === 'function' && record) {
this.#name = (await this.options.rename(record, attributeName, originalName));
}
else if (originalName && this.options.rename === false) {
this.#name = originalName;
}
if (this.#name && record) {
const parameters = extractPathParameters(this.#name);
if (parameters) {
parameters.forEach((parameter) => {
const attribute = record.$attributes[parameter];
if (typeof attribute === 'string') {
const name = string.slug(string.noCase(string.escapeHTML(attribute.toLowerCase())));
this.#name = this.#name?.replace(`:${parameter}`, name);
}
});
}
}
return this;
}
async makeFolder(record) {
if (typeof this.options.folder === 'function' && record) {
this.#folder = (await this.options.folder(record));
}
else if (this.options.folder) {
this.#folder = this.options.folder;
}
if (this.#folder && record) {
const parameters = extractPathParameters(this.#folder);
if (parameters) {
parameters.forEach((parameter) => {
const attribute = record.$attributes[parameter];
if (typeof attribute === 'string') {
const name = string.slug(string.noCase(string.escapeHTML(attribute.toLowerCase())));
this.#folder = this.#folder?.replace(`:${parameter}`, name);
}
});
}
}
return this;
}
async put() {
if (Buffer.isBuffer(this.input)) {
await this.getDisk().put(this.path, this.input);
}
else if (this.input) {
await this.getDisk().copyFromFs(this.input, this.path);
}
}
async remove() {
await this.getDisk().delete(this.path);
if (this.originalPath) {
await this.getDisk().delete(this.originalPath);
}
}
/**
*
*/
toObject() {
return {
keyId: this.getKeyId(),
name: this.name,
extname: this.extname,
size: this.size,
meta: this.meta,
mimeType: this.mimeType,
path: this.path,
};
}
toJSON() {
if (this.url) {
return {
...this.toObject(),
url: this.url,
};
}
return this.toObject();
}
}