import type { Bundle, Composition } from 'fhir/r4'; const FALLBACK_PATIENT = 'unknown-patient'; const FALLBACK_DATE = 'unknown-date'; /** Filesystem-safe token: strip everything but alphanumerics/underscore/hyphen, collapse runs, trim edges. */ function safeToken(value: string, fallback: string): string { const cleaned = value .replace(/[^A-Za-z0-9_-]+/g, '-') .replace(/-+/g, '-') .replace(/^-|-$/g, ''); return cleaned || fallback; } /** The Bundle's `entry[0]` per the B3 FHIR-document contract, if it's actually a Composition. */ function compositionOf(bundle: Bundle): Composition | undefined { const first = bundle.entry?.[0]?.resource; return first?.resourceType === 'Composition' ? (first as Composition) : undefined; } /** Derive the `{patient}` filename token from `Composition.subject` (`Patient/{pid}`). */ function patientToken(composition: Composition | undefined): string { const ref = composition?.subject?.reference; const pid = ref?.startsWith('Patient/') ? ref.slice('Patient/'.length) : ref; return pid ? safeToken(pid, FALLBACK_PATIENT) : FALLBACK_PATIENT; } /** * Derive the `{anchorDate}` filename token. The signed Bundle carries no separate structured field * for the anchor's own pinned date - `buildLegalExportDocument` (infra * `aws/sam/services/api/src/utils/legal-export-document.ts`) only embeds it as the trailing * " - {date}" segment of `Composition.title` (`Care-View Legal Record - Patient/{pid} - * {anchor.date ?? nowIso}`). Falls back to `Composition.date` (the export's own generation time) * if the title doesn't parse as expected - never throws. */ function anchorDateToken(composition: Composition | undefined): string { const title = composition?.title ?? ''; const parts = title.split(' — '); const trailing = parts.length >= 3 ? parts[parts.length - 1]?.trim() : undefined; return safeToken(trailing || composition?.date || FALLBACK_DATE, FALLBACK_DATE); } /** * Downloads a signed B3 legal-export Bundle as pretty-printed FHIR JSON - the authoritative * artifact (`LegalRecordPrintView` is only a human-readable convenience copy of the same data). * * Filename: `akashic-legal-record-{patient}-{anchorDate}.json`, both tokens derived from the * Bundle's own `Composition` (entry[0]) so this stays a pure, single-argument, side-effecting * util with no dependency on caller-tracked state. * * Mirrors the existing Blob -> createObjectURL -> anchor-click -> revoke pattern already used by * `FhirDocumentReferenceDisplay`'s attachment download (no new browser API surface). */ export function downloadBundleJson(bundle: Bundle): void { const composition = compositionOf(bundle); const filename = `akashic-legal-record-${patientToken(composition)}-${anchorDateToken(composition)}.json`; const blob = new Blob([JSON.stringify(bundle, null, 2)], { type: 'application/fhir+json' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } export default downloadBundleJson;