Files
starr-philproperties/apps/api/services/chibisafe.service.js
T

178 lines
5.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// services/chibisafe.service.js
//
// Wraps the Chibisafe REST API.
//
// Environment variables expected:
// CHIBISAFE_BASE_URL – e.g. https://cdn.yourdomain.com
// CHIBISAFE_API_KEY – your personal / service-account API key
// CHIBISAFE_ALBUM_AVATARS – album UUID for avatar images
// CHIBISAFE_ALBUM_VIDEOS – album UUID for videos
// CHIBISAFE_ALBUM_DOCUMENTS – album UUID for documents (pdf, docx, ppt, txt…)
// CHIBISAFE_ALBUM_THUMBNAILS – album UUID for video thumbnails
// CHIBISAFE_ALBUM_ARCHIVED – album UUID used as the "trash" / archived album
const FormData = require("form-data");
const axios = require("axios");
// ─── Config ───────────────────────────────────────────────────────────────────
const BASE_URL = (process.env.CHIBISAFE_BASE_URL || "").replace(/\/$/, "");
const API_KEY = process.env.CHIBISAFE_API_KEY || "";
const ALBUMS = {
avatars: process.env.CHIBISAFE_ALBUM_AVATARS || null,
videos: process.env.CHIBISAFE_ALBUM_VIDEOS || null,
documents: process.env.CHIBISAFE_ALBUM_DOCUMENTS || null,
thumbnails: process.env.CHIBISAFE_ALBUM_THUMBNAILS || null,
images: process.env.CHIBISAFE_ALBUM_IMAGES || null, // ← new
archived: process.env.CHIBISAFE_ALBUM_ARCHIVED || null,
};
// ─── Internal helpers ─────────────────────────────────────────────────────────
function resolveAlbumUuid(ownerType = "") {
switch (ownerType) {
case "avatar": return ALBUMS.avatars;
case "video": return ALBUMS.videos;
case "document": return ALBUMS.documents;
case "thumbnail": return ALBUMS.thumbnails;
case "image": return ALBUMS.images;
default: return null;
}
}
function baseHeaders(extra = {}) {
return {
"x-api-key": API_KEY,
...extra,
};
}
// ─── Axios instance ───────────────────────────────────────────────────────────
const chibi = axios.create({
baseURL: BASE_URL,
maxBodyLength: Infinity, // ← required for large file uploads
maxContentLength: Infinity,
});
/**
* Thin axios wrapper that throws a descriptive error on non-2xx.
*/
async function chibiRequest(path, { method = "GET", headers = {}, data } = {}) {
try {
const res = await chibi.request({
url: path,
method,
headers,
data,
});
return res.data;
} catch (err) {
const status = err.response?.status;
const body = err.response?.data ?? {};
const msg = body?.message || body?.error || err.message;
const friendly = new Error(`[Chibisafe] ${status ?? "?"} – ${msg}`);
friendly.status = status;
friendly.chibiBody = body;
throw friendly;
}
}
// ─── Public API ───────────────────────────────────────────────────────────────
/**
* Upload a file to Chibisafe, optionally straight into a typed album.
*/
async function uploadFile({ buffer, originalname, mimetype, ownerType = "" }) {
if (!BASE_URL || !API_KEY) {
throw new Error("[Chibisafe] CHIBISAFE_BASE_URL or CHIBISAFE_API_KEY is not configured.");
}
const albumUuid = resolveAlbumUuid(ownerType);
const form = new FormData();
form.append("file", buffer, {
filename: originalname,
contentType: mimetype,
});
const contentLength = await new Promise((resolve, reject) => {
form.getLength((err, length) => (err ? reject(err) : resolve(length)));
});
const data = await chibiRequest("/api/upload", {
method: "POST",
headers: {
...baseHeaders(),
...form.getHeaders(),
"Content-Length": contentLength,
...(albumUuid ? { albumuuid: albumUuid } : {}),
},
data: form,
});
return { uuid: data.uuid, url: data.url, name: data.name };
}
/**
* Permanently delete one file from Chibisafe by its UUID.
*/
async function deleteFile(uuid) {
await chibiRequest(`/api/file/${uuid}`, {
method: "DELETE",
headers: baseHeaders(),
});
}
/**
* Move one or more files into the "archived" album.
*/
async function archiveFiles(uuids) {
if (!ALBUMS.archived) {
throw new Error("[Chibisafe] CHIBISAFE_ALBUM_ARCHIVED is not configured.");
}
const ids = Array.isArray(uuids) ? uuids : [uuids];
if (!ids.length) return;
await chibiRequest("/api/files/album/add", {
method: "POST",
headers: {
...baseHeaders(),
"Content-Type": "application/json",
},
data: {
files: ids,
albumUuid: ALBUMS.archived,
},
});
}
/**
* Move one or more files into a specific album by UUID.
*/
async function addFilesToAlbum(uuids, albumUuid) {
const ids = Array.isArray(uuids) ? uuids : [uuids];
await chibiRequest("/api/files/album/add", {
method: "POST",
headers: {
...baseHeaders(),
"Content-Type": "application/json",
},
data: {
files: ids,
albumUuid,
},
});
}
module.exports = {
uploadFile,
deleteFile,
archiveFiles,
addFilesToAlbum,
ALBUMS,
resolveAlbumUuid,
};