/** * Map Qsirch items back into our NAS convention: * * Qsirch fields observed: * - item.path = "Niederlassungen/NL20/2025/12/18" (directory) * - item.name = "Stapel_Seiten-4_Zeit-141039" (basename without extension) * - item.extension = "pdf" * * We strictly accept only: * //// * * And we build: * - filename: "." * - relativePath: "////" * * Any unexpected shape is rejected (returns null) as defense-in-depth. */ const BRANCH_RE = /^NL\d+$/; const YEAR_RE = /^\d{4}$/; const MONTH_RE = /^(0[1-9]|1[0-2])$/; const DAY_RE = /^(0[1-9]|[12]\d|3[01])$/; function stripLeadingSlash(p) { const s = String(p || ""); return s.startsWith("/") ? s.slice(1) : s; } function normalizePrefix(prefix) { let p = stripLeadingSlash(prefix); p = p.trim(); if (p.endsWith("/")) p = p.replace(/\/+$/, ""); return p; } function stripPrefix(pathValue, prefix) { const p = stripLeadingSlash(pathValue).trim(); const pref = normalizePrefix(prefix); if (!pref) return p; if (p === pref) return ""; if (p.startsWith(`${pref}/`)) return p.slice(pref.length + 1); return null; } function toFilename(baseName, ext) { const safeBase = String(baseName || "").trim(); const safeExt = String(ext || "").trim(); if (!safeBase) return null; if (!safeExt) return null; const lowerExt = safeExt.toLowerCase(); // We only support PDFs for the Lieferscheine workflow. if (lowerExt !== "pdf") return null; // Qsirch usually returns name without extension. If it already ends with ".pdf", // keep it as-is to avoid double extensions. if (safeBase.toLowerCase().endsWith(`.${lowerExt}`)) { return safeBase; } return `${safeBase}.${safeExt}`; } /** * @param {any} item - Qsirch item * @param {{ pathPrefix: string }} options * @returns {null | { * branch: string, * date: string, * year: string, * month: string, * day: string, * filename: string, * relativePath: string * }} */ export function mapQsirchItemToSearchItem(item, { pathPrefix }) { const dirPath = typeof item?.path === "string" ? item.path : null; const name = typeof item?.name === "string" ? item.name : null; const ext = typeof item?.extension === "string" ? item.extension : null; if (!dirPath || !name || !ext) return null; const stripped = stripPrefix(dirPath, pathPrefix); if (stripped === null) return null; const parts = stripped.split("/").filter(Boolean); // Must be exactly NLxx/YYYY/MM/DD if (parts.length !== 4) return null; const [branch, year, month, day] = parts; if (!BRANCH_RE.test(branch)) return null; if (!YEAR_RE.test(year)) return null; if (!MONTH_RE.test(month)) return null; if (!DAY_RE.test(day)) return null; const filename = toFilename(name, ext); if (!filename) return null; const date = `${year}-${month}-${day}`; const relativePath = `${branch}/${year}/${month}/${day}/${filename}`; return { branch, date, year, month, day, filename, relativePath }; }