async function fetchTrace(id, { invalidated = invalidation } = {}) {
const controller = new AbortController();
invalidated.then(() => controller.abort());
return fetch(`https://www.openstreetmap.org/trace/${id}/data`, {
signal: controller.signal
})
.then((res) => (res.status !== 200 ? null : res))
.catch((err) => null)
.then((res) => (res ? getText(res) : null))
.catch((err) => {
if (err.name === "AbortError") return null;
throw err;
});
function getText(res) {
const mime = res.headers.get("Content-Type");
switch (mime) {
case "application/gpx+xml":
return res.text();
case "application/x-gzip":
return res.arrayBuffer().then((buffer) => {
const decompressed = fflate.decompressSync(new Uint8Array(buffer));
return fflate.strFromU8(decompressed);
});
case "application/x-bzip2":
return res.arrayBuffer().then((buffer) => {
const decompressed = bzip2.simple(
bzip2.array(new Uint8Array(buffer))
);
return fflate.strFromU8(decompressed);
});
default:
throw Error(`unhandled MIME type: ${mime}`);
}
}
}