Summary
Generalize clients/web/src/lib/downloadFile.ts beyond JSON: a downloadBlob() core (temporary-anchor download with a deferred revokeObjectURL so the download isn't aborted), fileNameFromUri() filename sanitization, and an isHttpUrl() http(s) allowlist check.
Why
The Apps host's ui/download-file support (follow-up issue) needs to download arbitrary embedded resources (text/blob) and open http(s) resource links safely. The existing downloadFile.ts only handles JSON; this issue extends the library without any UI wiring.
Reference implementation (PR #1510)
Re-implement informed by these changes at 33fac3f:
Depends on
Nothing — Wave 1 foundation, parallel-safe. Consumed later by the ui/download-file issue.
Notes
- Keep existing
downloadJsonFile callers working (the PR refactors it on top of downloadBlob).
- Coverage gate ≥90 on all four dimensions.
Part of the PR #1510 decomposition (see tracking issue).
Summary
Generalize
clients/web/src/lib/downloadFile.tsbeyond JSON: adownloadBlob()core (temporary-anchor download with a deferredrevokeObjectURLso the download isn't aborted),fileNameFromUri()filename sanitization, and anisHttpUrl()http(s) allowlist check.Why
The Apps host's
ui/download-filesupport (follow-up issue) needs to download arbitrary embedded resources (text/blob) and open http(s) resource links safely. The existingdownloadFile.tsonly handles JSON; this issue extends the library without any UI wiring.Reference implementation (PR #1510)
Re-implement informed by these changes at
33fac3f:downloadBlob(),fileNameFromUri(),isHttpUrl(),setTimeout(..., 0)-deferredrevokeObjectURL()fix (+46/−9)Depends on
Nothing — Wave 1 foundation, parallel-safe. Consumed later by the
ui/download-fileissue.Notes
downloadJsonFilecallers working (the PR refactors it on top ofdownloadBlob).Part of the PR #1510 decomposition (see tracking issue).