59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
export const ACTION_RUNTIME = String.raw`
|
|
(function () {
|
|
if (window.__wrnexusActionsInstalled) return;
|
|
window.__wrnexusActionsInstalled = true;
|
|
|
|
function csrf() {
|
|
var match = document.cookie.match(/(?:^|;\s*)wrn-csrf=([^;]+)/);
|
|
return match ? decodeURIComponent(match[1]) : "";
|
|
}
|
|
|
|
function detail(form, name, extra) {
|
|
return Object.assign({ form: form, name: name }, extra || {});
|
|
}
|
|
|
|
function emit(form, phase, name, extra, cancelable) {
|
|
return form.dispatchEvent(new CustomEvent("wrnexus:action:" + phase, {
|
|
bubbles: true,
|
|
cancelable: !!cancelable,
|
|
detail: detail(form, name, extra),
|
|
}));
|
|
}
|
|
|
|
document.addEventListener("submit", function (event) {
|
|
var form = event.target && event.target.closest && event.target.closest("form[data-wrn-action]");
|
|
if (!form || event.defaultPrevented) return;
|
|
var name = form.getAttribute("data-wrn-action");
|
|
if (!name) return;
|
|
event.preventDefault();
|
|
var data = new FormData(form);
|
|
data.set("_wrnexus_action", name);
|
|
data.set("_csrf", csrf());
|
|
emit(form, "optimistic", name, { input: data }, true);
|
|
form.setAttribute("aria-busy", "true");
|
|
form.setAttribute("data-wrn-action-state", "pending");
|
|
emit(form, "pending", name, { input: data });
|
|
fetch(form.action || location.href, {
|
|
method: "POST",
|
|
body: data,
|
|
credentials: "same-origin",
|
|
headers: { accept: "application/json", "x-wrnexus-action": name, "x-csrf-token": csrf() },
|
|
}).then(async function (response) {
|
|
var payload;
|
|
try { payload = await response.json(); } catch (_) { payload = { error: await response.text() }; }
|
|
if (!response.ok) throw Object.assign(new Error(payload.error || "Action failed"), { response: response, payload: payload });
|
|
form.setAttribute("data-wrn-action-state", "success");
|
|
emit(form, "success", name, { data: payload.data, invalidated: payload.invalidated || [] });
|
|
if (payload.invalidated && payload.invalidated.length) {
|
|
window.dispatchEvent(new CustomEvent("wrnexus:cache:invalidate", { detail: { tags: payload.invalidated } }));
|
|
}
|
|
}).catch(function (error) {
|
|
form.setAttribute("data-wrn-action-state", "error");
|
|
emit(form, "error", name, { error: error, errors: error.payload && error.payload.errors });
|
|
}).finally(function () {
|
|
form.removeAttribute("aria-busy");
|
|
});
|
|
});
|
|
})();
|
|
`;
|