Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 15:49:16 -05:00
pkg-proxy/internal/server/static/cache-delete.js
Giles Westwood 8bebc560f7
Delete cached artifacts through the API and the UI (#491)
* Delete cached artifacts through the API and the UI

cache_delete (PROXY_CACHE_DELETE) registers
DELETE /api/cache/{ecosystem}/{name}/{version}, which removes a
version's cached files, or only ?filename=, so the next request fetches
them from the upstream again. Records are cleared and the stored objects
queued for deletion like a replaced artifact. Pushed archives are left
alone: a whole-version delete skips them and naming one answers 409.

With it enabled, the version page shows a Delete button for each cached
file and one for the whole version. The UI calls /ui/api/cache so the
same ingress rules that guard /ui guard its deletes. Neither route has
authentication of its own, so the option is off by default.

* Load the cache delete script from a static file

Move the version page's delete-button JavaScript into
static/cache-delete.js and load it with a script tag, as
packages-list.js does.

---------

Co-authored-by: Giles Westwood <201443+gilesw@users.noreply.github.com>
2026-10-20 11:35:08 +01:00

36 lines
1.5 KiB
JavaScript

// The first click arms a button and the second deletes, so a stray click
// removes nothing.
document.querySelectorAll('.cache-delete').forEach(button => {
button.addEventListener('click', async () => {
if (button.dataset.armed !== 'true') {
document.querySelectorAll('.cache-delete').forEach(other => {
other.dataset.armed = 'false';
other.textContent = other.dataset.label;
});
button.dataset.armed = 'true';
button.textContent = 'Click again to delete';
return;
}
const errorBox = document.getElementById('cache-delete-error');
let url = button.closest('[data-cache-url]').dataset.cacheUrl;
if (button.dataset.filename) {
url += '?filename=' + encodeURIComponent(button.dataset.filename);
}
button.disabled = true;
button.textContent = 'Deleting…';
try {
const resp = await fetch(url, { method: 'DELETE' });
if (!resp.ok) {
const body = await resp.json().catch(() => ({}));
throw new Error(body.message || `HTTP ${resp.status}`);
}
window.location.reload();
} catch (err) {
errorBox.textContent = 'Delete failed: ' + err.message;
errorBox.classList.remove('hidden');
button.disabled = false;
button.dataset.armed = 'false';
button.textContent = button.dataset.label;
}
});
});