mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
19 lines
1.3 KiB
JavaScript
19 lines
1.3 KiB
JavaScript
import { readFile, realpath, stat } from "node:fs/promises";
|
|
import { resolve, relative, isAbsolute, extname } from "node:path";
|
|
// Keep UI entrypoints and assets within the same bound as the installed host's
|
|
// MAX_PLUGIN_UI_ASSET_BYTES (crates/dbx-plugin-runtime/src/plugins/assets.rs).
|
|
const MAX_PLUGIN_UI_ASSET_BYTES = 32 * 1024 * 1024;
|
|
|
|
export async function readAsset(root, path) {
|
|
if (typeof path !== "string" || !path || path.includes("\0") || isAbsolute(path)) throw new Error("Invalid asset path");
|
|
const base = await realpath(root),
|
|
file = await realpath(resolve(base, path));
|
|
const rel = relative(base, file);
|
|
if (rel.startsWith("..") || isAbsolute(rel)) throw new Error("Asset is outside UI root");
|
|
const info = await stat(file);
|
|
if (!info.isFile()) throw new Error("Asset is not a file");
|
|
if (info.size > MAX_PLUGIN_UI_ASSET_BYTES) throw new Error(`Asset exceeds ${MAX_PLUGIN_UI_ASSET_BYTES} byte limit`);
|
|
const types = { ".html": "text/html", ".js": "text/javascript", ".css": "text/css", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp", ".svg": "image/svg+xml", ".woff2": "font/woff2" };
|
|
return { dataBase64: (await readFile(file)).toString("base64"), contentType: types[extname(file)] || "application/octet-stream" };
|
|
}
|