"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.a = saveMediaBuffer;exports.i = getMediaDir;exports.n = ensureMediaDir;exports.r = extractOriginalFilename;exports.t = void 0;var _loggerU3s76KST = require("./logger-U3s76KST.js"); var _imageOpsZjRT9yvG = require("./image-ops-ZjRT9yvG.js"); require("node:fs"); var _nodePath = _interopRequireDefault(require("node:path")); var _promises = _interopRequireDefault(require("node:fs/promises")); var _nodeCrypto = _interopRequireDefault(require("node:crypto")); require("node:stream/promises"); require("node:https");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };} //#region src/media/store.ts const resolveMediaDir = () => _nodePath.default.join((0, _loggerU3s76KST.T)(), "media"); const MEDIA_MAX_BYTES = exports.t = 5 * 1024 * 1024; const MAX_BYTES = MEDIA_MAX_BYTES; const MEDIA_FILE_MODE = 420; /** * Sanitize a filename for cross-platform safety. * Removes chars unsafe on Windows/SharePoint/all platforms. * Keeps: alphanumeric, dots, hyphens, underscores, Unicode letters/numbers. */ function sanitizeFilename(name) { const trimmed = name.trim(); if (!trimmed) return ""; return trimmed.replace(/[^\p{L}\p{N}._-]+/gu, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, 60); } /** * Extract original filename from path if it matches the embedded format. * Pattern: {original}---{uuid}.{ext} → returns "{original}.{ext}" * Falls back to basename if no pattern match, or "file.bin" if empty. */ function extractOriginalFilename(filePath) { const basename = _nodePath.default.basename(filePath); if (!basename) return "file.bin"; const ext = _nodePath.default.extname(basename); const match = _nodePath.default.basename(basename, ext).match(/^(.+)---[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i); if (match?.[1]) return `${match[1]}${ext}`; return basename; } function getMediaDir() { return resolveMediaDir(); } async function ensureMediaDir() { const mediaDir = resolveMediaDir(); await _promises.default.mkdir(mediaDir, { recursive: true, mode: 448 }); return mediaDir; } function isMissingPathError(err) { return err instanceof Error && "code" in err && err.code === "ENOENT"; } async function retryAfterRecreatingDir(dir, run) { try { return await run(); } catch (err) { if (!isMissingPathError(err)) throw err; await _promises.default.mkdir(dir, { recursive: true, mode: 448 }); return await run(); } } async function saveMediaBuffer(buffer, contentType, subdir = "inbound", maxBytes = MAX_BYTES, originalFilename) { if (buffer.byteLength > maxBytes) throw new Error(`Media exceeds ${(maxBytes / (1024 * 1024)).toFixed(0)}MB limit`); const dir = _nodePath.default.join(resolveMediaDir(), subdir); await _promises.default.mkdir(dir, { recursive: true, mode: 448 }); const uuid = _nodeCrypto.default.randomUUID(); const headerExt = (0, _imageOpsZjRT9yvG.l)(contentType?.split(";")[0]?.trim() ?? void 0); const mime = await (0, _imageOpsZjRT9yvG.c)({ buffer, headerMime: contentType }); const ext = headerExt ?? (0, _imageOpsZjRT9yvG.l)(mime) ?? ""; let id; if (originalFilename) { const base = _nodePath.default.parse(originalFilename).name; const sanitized = sanitizeFilename(base); id = sanitized ? `${sanitized}---${uuid}${ext}` : `${uuid}${ext}`; } else id = ext ? `${uuid}${ext}` : uuid; const dest = _nodePath.default.join(dir, id); await retryAfterRecreatingDir(dir, () => _promises.default.writeFile(dest, buffer, { mode: MEDIA_FILE_MODE })); return { id, path: dest, size: buffer.byteLength, contentType: mime }; } //#endregion /* v9-4f43f471a2bdd19d */