Files
yara724api/src/helpers/urlCreator.ts
2026-06-13 17:43:33 +03:30

63 lines
2.1 KiB
TypeScript

type StoredFileCapture = {
url?: string;
path?: string;
};
/**
* Reduce any stored file reference to the canonical relative storage path
* (e.g. `files/claim-captures/x.jpg`).
*
* Handles values that were persisted as absolute URLs on a different portal
* (e.g. `https://host/car-damage/user/api/files/...`) so we never leak a
* baked-in host/prefix into responses served from another origin.
*/
function toRelativeFilePath(value: string | null | undefined): string {
const s = String(value ?? "").trim();
if (!s) return "";
// Prefer the `files/...` segment wherever it appears in the string.
const match = s.match(/(?:^|\/)(files\/.+)$/i);
if (match) return match[1];
// No recognizable file root: keep external URLs intact, otherwise strip
// any leading slashes so we can safely prefix the base URL.
if (/^https?:\/\//i.test(s)) return s;
return s.replace(/^\/+/, "");
}
/**
* Build a public file URL from a stored path (relative or absolute).
*
* The link is always rebuilt from the current `URL` env, so deployments with
* custom routing (different sub-paths per portal) stay correct even when the
* persisted value was created elsewhere.
*/
export function buildFileLink(path: string): string {
const relative = toRelativeFilePath(path);
if (!relative) return "";
// Already an absolute external URL with no recognizable file root.
if (/^https?:\/\//i.test(relative)) return relative;
const baseUrl = (process.env.URL ?? "").replace(/\/+$/, "");
if (process.env.NODE_ENV === "local") {
return `${baseUrl}/${relative}`;
}
return `${baseUrl}/api/${relative}`;
}
/**
* Resolve a file URL from persisted capture metadata.
*
* Prefer `path`, fall back to `url`, and always rebuild through
* {@link buildFileLink} so stale portal-prefixed values (e.g. `.../user/api/...`)
* are normalized to the current server origin.
*/
export function resolveStoredFileUrl(
stored?: StoredFileCapture | null,
): string | undefined {
const source = stored?.path?.trim() || stored?.url?.trim();
if (!source) return undefined;
return buildFileLink(source);
}