fix: address code review findings for DNS management
- CRITICAL: Change DNS zones endpoint from GET to POST to avoid leaking API token in URL query parameters - HIGH: Add sync.RWMutex to protect dnsProvider field in Server, Deployer, and proxy Manager against concurrent read/write races - HIGH: Capture old DNS provider reference synchronously before launching background cleanup goroutine - HIGH: Use getDNS()/getDNSProviderLocked() accessors instead of direct field reads in all DNS operations
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import { a as attr, b as attr_class, c as clsx, e as escape_html, s as store_get, f as ensure_array_like, u as unsubscribe_stores, k as bind_props, i as derived } from "./index.js";
|
||||
import { I as IconX } from "./IconX.js";
|
||||
import { t } from "./index2.js";
|
||||
/* empty css */
|
||||
function html(value) {
|
||||
var html2 = String(value ?? "");
|
||||
var open = "<!---->";
|
||||
return open + html2 + "<!---->";
|
||||
}
|
||||
function IconSearch($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.3-4.3"></path></svg>`);
|
||||
}
|
||||
function EntityPicker($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
var $$store_subs;
|
||||
const {
|
||||
open = void 0,
|
||||
items,
|
||||
current = "",
|
||||
placeholder,
|
||||
title = "",
|
||||
onselect,
|
||||
onclose
|
||||
} = $$props;
|
||||
let query = "";
|
||||
let highlightIndex = 0;
|
||||
const filtered = derived(() => {
|
||||
const q = query.toLowerCase().trim();
|
||||
if (!q) return items;
|
||||
return items.filter((item) => item.label.toLowerCase().includes(q) || (item.description?.toLowerCase().includes(q) ?? false));
|
||||
});
|
||||
const grouped = derived(() => {
|
||||
const groups = [];
|
||||
const seen = /* @__PURE__ */ new Map();
|
||||
for (const item of filtered()) {
|
||||
const groupName = item.group ?? "";
|
||||
const idx = seen.get(groupName);
|
||||
if (idx !== void 0) {
|
||||
groups[idx].items.push(item);
|
||||
} else {
|
||||
seen.set(groupName, groups.length);
|
||||
groups.push({ name: groupName, items: [item] });
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
});
|
||||
const flatFiltered = derived(filtered);
|
||||
function flatIndexOf(groupIdx, itemIdx) {
|
||||
let index = 0;
|
||||
for (let g = 0; g < groupIdx; g++) {
|
||||
index += grouped()[g].items.length;
|
||||
}
|
||||
return index + itemIdx;
|
||||
}
|
||||
if (open) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<div class="entity-picker-backdrop svelte-1bxz98v"></div> <div class="entity-picker-container svelte-1bxz98v"><div class="entity-picker-modal svelte-1bxz98v" role="dialog" aria-modal="true"${attr("aria-label", title)}>`);
|
||||
if (title) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<div class="entity-picker-header svelte-1bxz98v"><h2 class="entity-picker-title svelte-1bxz98v">${escape_html(title)}</h2> <button type="button" class="entity-picker-close svelte-1bxz98v" aria-label="Close">`);
|
||||
IconX($$renderer2, { size: 18 });
|
||||
$$renderer2.push(`<!----></button></div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <div class="entity-picker-search svelte-1bxz98v">`);
|
||||
IconSearch($$renderer2, { size: 16, class: "entity-picker-search-icon" });
|
||||
$$renderer2.push(`<!----> <input${attr("value", query)} type="text" class="entity-picker-search-input svelte-1bxz98v"${attr("placeholder", placeholder ?? store_get($$store_subs ??= {}, "$t", t)("entityPicker.search"))} autocomplete="off" spellcheck="false"/> `);
|
||||
if (!title) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<button type="button" class="entity-picker-close-inline svelte-1bxz98v" aria-label="Close">`);
|
||||
IconX($$renderer2, { size: 16 });
|
||||
$$renderer2.push(`<!----></button>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div> <div class="entity-picker-list svelte-1bxz98v">`);
|
||||
if (flatFiltered().length === 0) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<div class="entity-picker-empty svelte-1bxz98v">${escape_html(store_get($$store_subs ??= {}, "$t", t)("entityPicker.noResults"))}</div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
$$renderer2.push(`<!--[-->`);
|
||||
const each_array = ensure_array_like(grouped());
|
||||
for (let gIdx = 0, $$length = each_array.length; gIdx < $$length; gIdx++) {
|
||||
let group = each_array[gIdx];
|
||||
if (group.name) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<div class="entity-picker-group-header svelte-1bxz98v">${escape_html(group.name)}</div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <!--[-->`);
|
||||
const each_array_1 = ensure_array_like(group.items);
|
||||
for (let iIdx = 0, $$length2 = each_array_1.length; iIdx < $$length2; iIdx++) {
|
||||
let item = each_array_1[iIdx];
|
||||
const flatIdx = flatIndexOf(gIdx, iIdx);
|
||||
const isHighlighted = flatIdx === highlightIndex;
|
||||
const isCurrent = item.value === current;
|
||||
$$renderer2.push(`<button type="button"${attr_class("entity-picker-item svelte-1bxz98v", void 0, {
|
||||
"entity-picker-item--highlighted": isHighlighted && !item.disabled,
|
||||
"entity-picker-item--current": isCurrent,
|
||||
"entity-picker-item--disabled": item.disabled
|
||||
})}${attr("data-highlighted", isHighlighted)}${attr("disabled", item.disabled, true)}>`);
|
||||
if (item.icon) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<span class="entity-picker-item-icon svelte-1bxz98v">${html(item.icon)}</span>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> <span class="entity-picker-item-content svelte-1bxz98v"><span class="entity-picker-item-label svelte-1bxz98v">${escape_html(item.label)}</span> `);
|
||||
if (item.disabledHint) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<span class="entity-picker-item-hint svelte-1bxz98v">${escape_html(item.disabledHint)}</span>`);
|
||||
} else if (item.description) {
|
||||
$$renderer2.push("<!--[1-->");
|
||||
$$renderer2.push(`<span class="entity-picker-item-description svelte-1bxz98v">${escape_html(item.description)}</span>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></span></button>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div></div></div>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
if ($$store_subs) unsubscribe_stores($$store_subs);
|
||||
bind_props($$props, { open });
|
||||
});
|
||||
}
|
||||
export {
|
||||
EntityPicker as E,
|
||||
IconSearch as I
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import { a as attr, e as escape_html, b as attr_class, k as bind_props, g as stringify } from "./index.js";
|
||||
function FormField($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
let {
|
||||
label,
|
||||
name,
|
||||
type = "text",
|
||||
value = "",
|
||||
placeholder = "",
|
||||
required = false,
|
||||
disabled = false,
|
||||
error = "",
|
||||
helpText = "",
|
||||
oninput
|
||||
} = $$props;
|
||||
const inputBase = "w-full rounded-lg border px-3 py-2 text-sm transition-all duration-150 focus:outline-none focus:ring-2 bg-[var(--surface-input)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)]";
|
||||
const inputNormal = "border-[var(--border-input)] focus:ring-[var(--color-brand-500)] focus:border-[var(--color-brand-500)]";
|
||||
const inputError = "border-[var(--color-danger)] focus:ring-[var(--color-danger)]";
|
||||
const inputDisabled = "opacity-60 cursor-not-allowed bg-[var(--surface-card-hover)]";
|
||||
$$renderer2.push(`<div class="flex flex-col gap-1.5"><label${attr("for", name)} class="text-sm font-medium text-[var(--text-primary)]">${escape_html(label)} `);
|
||||
if (required) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<span class="text-[var(--color-danger)]">*</span>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></label> `);
|
||||
if (type === "textarea") {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<textarea${attr("id", name)}${attr("name", name)}${attr("placeholder", placeholder)}${attr("required", required, true)}${attr("disabled", disabled, true)}${attr_class(`${stringify(inputBase)} ${stringify(error ? inputError : inputNormal)} ${stringify(disabled ? inputDisabled : "")}`)} rows="3">`);
|
||||
const $$body = escape_html(value);
|
||||
if ($$body) {
|
||||
$$renderer2.push(`${$$body}`);
|
||||
}
|
||||
$$renderer2.push(`</textarea>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
$$renderer2.push(`<input${attr("id", name)}${attr("name", name)}${attr("type", type)}${attr("value", value)}${attr("placeholder", placeholder)}${attr("required", required, true)}${attr("disabled", disabled, true)}${attr_class(`${stringify(inputBase)} ${stringify(error ? inputError : inputNormal)} ${stringify(disabled ? inputDisabled : "")}`)}/>`);
|
||||
}
|
||||
$$renderer2.push(`<!--]--> `);
|
||||
if (error) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<p class="text-xs text-[var(--color-danger)]">${escape_html(error)}</p>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--> `);
|
||||
if (helpText && !error) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
$$renderer2.push(`<p class="text-xs text-[var(--text-tertiary)]">${escape_html(helpText)}</p>`);
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]--></div>`);
|
||||
bind_props($$props, { value });
|
||||
});
|
||||
}
|
||||
export {
|
||||
FormField as F
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconAlert($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconAlert as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconCheck($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconCheck as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconChevronRight($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="m9 18 6-6-6-6"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconChevronRight as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconDeploy($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M15.59 14.37a6 6 0 0 1-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 0 0 6.16-12.12A14.98 14.98 0 0 0 9.631 8.41m5.96 5.96a14.926 14.926 0 0 1-5.841 2.58m-.119-8.54a6 6 0 0 0-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 0 0-2.58 5.84m2.699 2.7a15.09 15.09 0 0 1-2.448-2.448 14.9 14.9 0 0 1 .06-.312m-2.24 2.39a4.493 4.493 0 0 0-1.757 4.306 4.493 4.493 0 0 0 4.306-1.758M16.5 9a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Z"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconDeploy as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconGlobe($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"></path><path d="M2 12h20"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconGlobe as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, g as stringify } from "./index.js";
|
||||
function IconLoader($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(`animate-spin ${stringify(c)}`)} aria-hidden="true"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconLoader as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconPlus($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconPlus as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconSettings($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path><circle cx="12" cy="12" r="3"></circle></svg>`);
|
||||
}
|
||||
export {
|
||||
IconSettings as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconTrash($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M3 6h18"></path><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path><line x1="10" x2="10" y1="11" y2="17"></line><line x1="14" x2="14" y1="11" y2="17"></line></svg>`);
|
||||
}
|
||||
export {
|
||||
IconTrash as I
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { a as attr, b as attr_class, c as clsx } from "./index.js";
|
||||
function IconX($$renderer, $$props) {
|
||||
const { size = 20, class: c = "" } = $$props;
|
||||
$$renderer.push(`<svg xmlns="http://www.w3.org/2000/svg"${attr("width", size)}${attr("height", size)} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"${attr_class(clsx(c))} aria-hidden="true"><path d="M18 6 6 18"></path><path d="m6 6 12 12"></path></svg>`);
|
||||
}
|
||||
export {
|
||||
IconX as I
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
import { b as attr_class, l as attr_style, g as stringify } from "./index.js";
|
||||
function Skeleton($$renderer, $$props) {
|
||||
const {
|
||||
class: className = "",
|
||||
width = "100%",
|
||||
height = "1rem",
|
||||
rounded = false
|
||||
} = $$props;
|
||||
$$renderer.push(`<div${attr_class(`skeleton ${stringify(className)}`)}${attr_style(`width: ${stringify(width)}; height: ${stringify(height)}; ${stringify(rounded ? "border-radius: 9999px;" : "")}`)} aria-hidden="true"></div>`);
|
||||
}
|
||||
export {
|
||||
Skeleton as S
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import "clsx";
|
||||
import { S as Skeleton } from "./Skeleton.js";
|
||||
function SkeletonCard($$renderer) {
|
||||
$$renderer.push(`<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-5 shadow-[var(--shadow-sm)]"><div class="flex items-start justify-between"><div class="flex-1 space-y-2">`);
|
||||
Skeleton($$renderer, { width: "60%", height: "1.25rem" });
|
||||
$$renderer.push(`<!----> `);
|
||||
Skeleton($$renderer, { width: "80%", height: "0.875rem" });
|
||||
$$renderer.push(`<!----></div> `);
|
||||
Skeleton($$renderer, { width: "4rem", height: "1.5rem", rounded: true });
|
||||
$$renderer.push(`<!----></div> <div class="mt-4 flex gap-4">`);
|
||||
Skeleton($$renderer, { width: "5rem", height: "0.875rem" });
|
||||
$$renderer.push(`<!----> `);
|
||||
Skeleton($$renderer, { width: "4rem", height: "0.875rem" });
|
||||
$$renderer.push(`<!----></div> <div class="mt-3 flex gap-3">`);
|
||||
Skeleton($$renderer, { width: "3.5rem", height: "0.75rem" });
|
||||
$$renderer.push(`<!----> `);
|
||||
Skeleton($$renderer, { width: "4.5rem", height: "0.75rem" });
|
||||
$$renderer.push(`<!----></div></div>`);
|
||||
}
|
||||
export {
|
||||
SkeletonCard as S
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
const TOKEN_KEY = "auth_token";
|
||||
function getAuthToken() {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
return localStorage.getItem(TOKEN_KEY);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function clearAuth() {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
}
|
||||
}
|
||||
class ApiError extends Error {
|
||||
constructor(message, status) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
this.name = "ApiError";
|
||||
}
|
||||
}
|
||||
async function request(path, init) {
|
||||
const token = getAuthToken();
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
...init?.headers
|
||||
};
|
||||
if (token) {
|
||||
headers["Authorization"] = `Bearer ${token}`;
|
||||
}
|
||||
const res = await fetch(path, {
|
||||
...init,
|
||||
headers
|
||||
});
|
||||
if (res.status === 401 && typeof window !== "undefined" && !path.includes("/auth/")) {
|
||||
clearAuth();
|
||||
window.location.href = "/login";
|
||||
throw new ApiError("Authentication required", 401);
|
||||
}
|
||||
let envelope;
|
||||
try {
|
||||
envelope = await res.json();
|
||||
} catch {
|
||||
throw new ApiError(
|
||||
`Server returned non-JSON response (HTTP ${res.status})`,
|
||||
res.status
|
||||
);
|
||||
}
|
||||
if (!envelope.success) {
|
||||
throw new ApiError(envelope.error ?? "Unknown API error", res.status);
|
||||
}
|
||||
return envelope.data;
|
||||
}
|
||||
function post(path, body) {
|
||||
return request(path, {
|
||||
method: "POST",
|
||||
body: body !== void 0 ? JSON.stringify(body) : void 0
|
||||
});
|
||||
}
|
||||
function validateProxy(host, port) {
|
||||
return post("/api/proxies/validate", { host, port });
|
||||
}
|
||||
function cleanupStaleContainer(id) {
|
||||
return post(`/api/containers/stale/${id}/cleanup`);
|
||||
}
|
||||
function bulkCleanupStaleContainers() {
|
||||
return post("/api/containers/stale/cleanup");
|
||||
}
|
||||
export {
|
||||
bulkCleanupStaleContainers as b,
|
||||
cleanupStaleContainer as c,
|
||||
validateProxy as v
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
let base = "";
|
||||
let assets = base;
|
||||
const app_dir = "_app";
|
||||
const relative = true;
|
||||
const initial = { base, assets };
|
||||
function override(paths) {
|
||||
base = paths.base;
|
||||
assets = paths.assets;
|
||||
}
|
||||
function reset() {
|
||||
base = initial.base;
|
||||
assets = initial.assets;
|
||||
}
|
||||
function set_assets(path) {
|
||||
assets = initial.assets = path;
|
||||
}
|
||||
let prerendering = false;
|
||||
function set_building() {
|
||||
}
|
||||
function set_prerendering() {
|
||||
prerendering = true;
|
||||
}
|
||||
export {
|
||||
set_building as a,
|
||||
set_prerendering as b,
|
||||
base as c,
|
||||
app_dir as d,
|
||||
assets as e,
|
||||
reset as f,
|
||||
override as o,
|
||||
prerendering as p,
|
||||
relative as r,
|
||||
set_assets as s
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
const SCHEME = /^[a-z][a-z\d+\-.]+:/i;
|
||||
const internal = new URL("sveltekit-internal://");
|
||||
function resolve(base, path) {
|
||||
if (path[0] === "/" && path[1] === "/") return path;
|
||||
let url = new URL(base, internal);
|
||||
url = new URL(path, url);
|
||||
return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href;
|
||||
}
|
||||
function normalize_path(path, trailing_slash) {
|
||||
if (path === "/" || trailing_slash === "ignore") return path;
|
||||
if (trailing_slash === "never") {
|
||||
return path.endsWith("/") ? path.slice(0, -1) : path;
|
||||
} else if (trailing_slash === "always" && !path.endsWith("/")) {
|
||||
return path + "/";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
function decode_pathname(pathname) {
|
||||
return pathname.split("%25").map(decodeURI).join("%25");
|
||||
}
|
||||
function decode_params(params) {
|
||||
for (const key in params) {
|
||||
params[key] = decodeURIComponent(params[key]);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
function make_trackable(url, callback, search_params_callback, allow_hash = false) {
|
||||
const tracked = new URL(url);
|
||||
Object.defineProperty(tracked, "searchParams", {
|
||||
value: new Proxy(tracked.searchParams, {
|
||||
get(obj, key) {
|
||||
if (key === "get" || key === "getAll" || key === "has") {
|
||||
return (param, ...rest) => {
|
||||
search_params_callback(param);
|
||||
return obj[key](param, ...rest);
|
||||
};
|
||||
}
|
||||
callback();
|
||||
const value = Reflect.get(obj, key);
|
||||
return typeof value === "function" ? value.bind(obj) : value;
|
||||
}
|
||||
}),
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
const tracked_url_properties = ["href", "pathname", "search", "toString", "toJSON"];
|
||||
if (allow_hash) tracked_url_properties.push("hash");
|
||||
for (const property of tracked_url_properties) {
|
||||
Object.defineProperty(tracked, property, {
|
||||
get() {
|
||||
callback();
|
||||
return url[property];
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
{
|
||||
tracked[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
|
||||
return inspect(url, opts);
|
||||
};
|
||||
tracked.searchParams[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
|
||||
return inspect(url.searchParams, opts);
|
||||
};
|
||||
}
|
||||
if (!allow_hash) {
|
||||
disable_hash(tracked);
|
||||
}
|
||||
return tracked;
|
||||
}
|
||||
function disable_hash(url) {
|
||||
allow_nodejs_console_log(url);
|
||||
Object.defineProperty(url, "hash", {
|
||||
get() {
|
||||
throw new Error(
|
||||
"Cannot access event.url.hash. Consider using `page.url.hash` inside a component instead"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
function disable_search(url) {
|
||||
allow_nodejs_console_log(url);
|
||||
for (const property of ["search", "searchParams"]) {
|
||||
Object.defineProperty(url, property, {
|
||||
get() {
|
||||
throw new Error(`Cannot access url.${property} on a page with prerendering enabled`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function allow_nodejs_console_log(url) {
|
||||
{
|
||||
url[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
|
||||
return inspect(new URL(url), opts);
|
||||
};
|
||||
}
|
||||
}
|
||||
function validator(expected) {
|
||||
function validate(module, file) {
|
||||
if (!module) return;
|
||||
for (const key in module) {
|
||||
if (key[0] === "_" || expected.has(key)) continue;
|
||||
const values = [...expected.values()];
|
||||
const hint = hint_for_supported_files(key, file?.slice(file.lastIndexOf("."))) ?? `valid exports are ${values.join(", ")}, or anything with a '_' prefix`;
|
||||
throw new Error(`Invalid export '${key}'${file ? ` in ${file}` : ""} (${hint})`);
|
||||
}
|
||||
}
|
||||
return validate;
|
||||
}
|
||||
function hint_for_supported_files(key, ext = ".js") {
|
||||
const supported_files = [];
|
||||
if (valid_layout_exports.has(key)) {
|
||||
supported_files.push(`+layout${ext}`);
|
||||
}
|
||||
if (valid_page_exports.has(key)) {
|
||||
supported_files.push(`+page${ext}`);
|
||||
}
|
||||
if (valid_layout_server_exports.has(key)) {
|
||||
supported_files.push(`+layout.server${ext}`);
|
||||
}
|
||||
if (valid_page_server_exports.has(key)) {
|
||||
supported_files.push(`+page.server${ext}`);
|
||||
}
|
||||
if (valid_server_exports.has(key)) {
|
||||
supported_files.push(`+server${ext}`);
|
||||
}
|
||||
if (supported_files.length > 0) {
|
||||
return `'${key}' is a valid export in ${supported_files.slice(0, -1).join(", ")}${supported_files.length > 1 ? " or " : ""}${supported_files.at(-1)}`;
|
||||
}
|
||||
}
|
||||
const valid_layout_exports = /* @__PURE__ */ new Set([
|
||||
"load",
|
||||
"prerender",
|
||||
"csr",
|
||||
"ssr",
|
||||
"trailingSlash",
|
||||
"config"
|
||||
]);
|
||||
const valid_page_exports = /* @__PURE__ */ new Set([...valid_layout_exports, "entries"]);
|
||||
const valid_layout_server_exports = /* @__PURE__ */ new Set([...valid_layout_exports]);
|
||||
const valid_page_server_exports = /* @__PURE__ */ new Set([...valid_layout_server_exports, "actions", "entries"]);
|
||||
const valid_server_exports = /* @__PURE__ */ new Set([
|
||||
"GET",
|
||||
"POST",
|
||||
"PATCH",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD",
|
||||
"fallback",
|
||||
"prerender",
|
||||
"trailingSlash",
|
||||
"config",
|
||||
"entries"
|
||||
]);
|
||||
const validate_layout_exports = validator(valid_layout_exports);
|
||||
const validate_page_exports = validator(valid_page_exports);
|
||||
const validate_layout_server_exports = validator(valid_layout_server_exports);
|
||||
const validate_page_server_exports = validator(valid_page_server_exports);
|
||||
const validate_server_exports = validator(valid_server_exports);
|
||||
export {
|
||||
SCHEME as S,
|
||||
decode_params as a,
|
||||
validate_layout_exports as b,
|
||||
validate_page_server_exports as c,
|
||||
disable_search as d,
|
||||
validate_page_exports as e,
|
||||
decode_pathname as f,
|
||||
validate_server_exports as g,
|
||||
make_trackable as m,
|
||||
normalize_path as n,
|
||||
resolve as r,
|
||||
validate_layout_server_exports as v
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
const BROWSER = false;
|
||||
export {
|
||||
BROWSER as B
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { d as ssr_context } from "./index.js";
|
||||
import "clsx";
|
||||
function onDestroy(fn) {
|
||||
/** @type {SSRContext} */
|
||||
ssr_context.r.on_destroy(fn);
|
||||
}
|
||||
export {
|
||||
onDestroy as o
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
import { w as writable, d as derived } from "./index3.js";
|
||||
const app$1 = { "name": "Docker Watcher", "version": "v0.1" };
|
||||
const health$1 = { "connected": "connected", "disconnected": "disconnected", "rawError": "Technical details", "retryNow": "Retry now" };
|
||||
const nav$1 = { "dashboard": "Dashboard", "projects": "Projects", "deploy": "Deploy", "proxies": "Proxies", "events": "Events", "settings": "Settings", "logout": "Log out" };
|
||||
const dashboard$1 = { "title": "Dashboard", "quickDeploy": "Quick Deploy", "totalProjects": "Total Projects", "runningInstances": "Running Instances", "failedInstances": "Failed Instances", "projects": "Projects", "retry": "Retry", "noProjects": "No projects yet.", "addFirst": "Add your first project", "loadFailed": "Failed to load dashboard", "staleContainers": "Stale Containers" };
|
||||
const projects$1 = { "title": "Projects", "addProject": "Add Project", "cancel": "Cancel", "newProject": "New Project", "name": "Name", "image": "Image", "port": "Port", "registry": "Registry", "created": "Created", "view": "View", "noProjects": "No projects configured yet.", "getStarted": 'Click "Add Project" to get started.', "createProject": "Create Project", "creating": "Creating...", "healthcheck": "Healthcheck Path", "nameRequired": "Name and image are required.", "loadFailed": "Failed to load projects", "createFailed": "Failed to create project", "browseImages": "Browse Images", "selectImage": "Select an image", "noImages": "No images found", "loadingImages": "Loading images...", "imageLoadFailed": "Failed to load images" };
|
||||
const projectDetail$1 = { "deleteProject": "Delete Project", "envVars": "Environment Variables", "volumes": "Volume Mounts", "stages": "Stages", "noStages": "No stages configured for this project.", "pattern": "Pattern", "autoDeploy": "auto-deploy", "requiresConfirm": "requires confirm", "instances": "instances", "deployNewVersion": "Deploy new version", "selectTag": "Select tag to deploy", "loadingTags": "Loading tags...", "chooseTag": "Choose a tag...", "enterTag": "Enter image tag (e.g., dev-abc123)", "deploy": "Deploy", "deploying": "Deploying...", "recentDeploys": "Recent Deploys", "noDeployHistory": "No deploy history for this project.", "tag": "Tag", "status": "Status", "started": "Started", "finished": "Finished", "error": "Error", "noInstancesRunning": "No instances running", "deleteConfirmTitle": "Delete Project", "deleteConfirmMessage": "This will permanently delete the project '{name}' and all its stages, instances, and deploy history. This cannot be undone.", "loadFailed": "Failed to load project", "deleteFailed": "Failed to delete project", "deployFailed": "Deploy failed" };
|
||||
const envEditor$1 = { "title": "Environment Variables", "description": "Manage per-stage environment variable overrides. Stage-level values override project-level defaults.", "stage": "Stage", "projectDefaults": "Project-Level Defaults", "stageOverrides": "Stage Overrides", "key": "Key", "value": "Value", "secret": "Secret", "source": "Source", "actions": "Actions", "overridden": "overridden", "inherited": "inherited", "overridesProject": "overrides project", "stageOnly": "stage only", "edit": "Edit", "change": "Change", "delete": "Delete", "save": "Save", "add": "Add", "adding": "Adding...", "noStages": "No stages configured. Add stages to the project first.", "loadFailed": "Failed to load project", "envAdded": "Environment variable added", "envUpdated": "Environment variable updated", "envDeleted": "Environment variable deleted", "addFailed": "Failed to add env var", "updateFailed": "Failed to update env var", "deleteFailed": "Failed to delete env var", "loadEnvFailed": "Failed to load env vars" };
|
||||
const volumeEditor$1 = { "title": "Volume Mounts", "description": "Configure volume mounts for containers. Choose a scope to control how volumes are shared between deploys.", "sourceHost": "Source (Host)", "targetContainer": "Target (Container)", "scope": "Scope", "nameColumn": "Name", "namePlaceholder": "e.g. shared-db", "requiresName": "requires name", "noHostPath": "no host path", "tmpfs": "tmpfs (in-memory)", "actions": "Actions", "edit": "Edit", "delete": "Delete", "save": "Save", "add": "Add", "adding": "Adding...", "noVolumes": "No volumes configured yet. Add one above.", "volumeAdded": "Volume added", "volumeUpdated": "Volume updated", "volumeDeleted": "Volume deleted", "loadFailed": "Failed to load volumes", "addFailed": "Failed to add volume", "updateFailed": "Failed to update volume", "deleteFailed": "Failed to delete volume" };
|
||||
const volumeBrowser$1 = { "title": "Volume Browser", "loadFailed": "Failed to load directory", "empty": "This directory is empty.", "name": "Name", "size": "Size", "modified": "Modified", "downloadAll": "Download volume as ZIP", "downloadFolder": "Download folder as ZIP", "upload": "Upload files", "uploaded": "Uploaded", "files": "file(s)", "uploadFailed": "Failed to upload files", "browse": "Browse", "download": "Download" };
|
||||
const quickDeploy$1 = { "title": "Quick Deploy", "description": "Deploy a container image with zero configuration. Paste an image URL, review the defaults, and deploy.", "step1": "1. Enter Image URL", "imageUrl": "Image URL", "imageUrlHelp": "Full image URL including tag (e.g., git.example.com/user/app:dev-abc123)", "inspect": "Inspect", "inspecting": "Inspecting...", "step2": "2. Review Configuration", "reviewDesc": "These defaults were detected from the image. Adjust as needed before deploying.", "projectName": "Project Name", "port": "Port", "portHelp": "Container port to expose (1-65535)", "healthCheckPath": "Health Check Path", "healthCheckHelp": "Optional HTTP path for health verification", "stage": "Stage", "development": "Development", "release": "Release", "production": "Production", "stageHelp": "Deployment stage for this image", "subdomainOverride": "Subdomain Override", "subdomainHelp": "Leave empty to use the default subdomain pattern", "envVars": "Environment Variables", "envVarsHelp": "One per line, KEY=VALUE format", "step3": "3. Deploy", "deployDesc": "A new project will be created and the container will be deployed immediately.", "deployBtn": "Deploy", "inspectedSuccess": "Image inspected successfully", "deployedSuccess": "Deployed {name} successfully!", "inspectFailed": "Failed to inspect image", "deployFailed": "Deployment failed", "browseImages": "Browse", "selectImage": "Select an image from a registry", "noImages": "No images found", "loadingImages": "Loading...", "imageLoadFailed": "Failed to load images" };
|
||||
const settings$1 = { "title": "Settings", "general": "General", "registries": "Registries", "credentials": "Credentials", "authentication": "Authentication", "appearance": "Appearance", "staleThreshold": "Stale threshold (days)", "staleThresholdHelp": "Containers inactive for longer than this will be flagged as stale." };
|
||||
const settingsGeneral$1 = { "title": "General Settings", "globalConfig": "Global Configuration", "domain": "Domain", "domainHelp": "Base domain for subdomain routing", "serverIp": "Server IP", "serverIpHelp": "Public IP address of the server", "dockerNetwork": "Docker Network", "dockerNetworkHelp": "Docker network for deployed containers", "subdomainPattern": "Subdomain Pattern", "subdomainPatternHelp": "Pattern for auto-generated subdomains", "pollingInterval": "Polling Interval (seconds)", "pollingIntervalHelp": "How often to check registries for new tags (10-86400)", "notificationUrl": "Notification URL", "notificationUrlHelp": "Webhook URL for deploy notifications", "saveSettings": "Save Settings", "saving": "Saving...", "saved": "Settings saved successfully", "saveFailed": "Failed to save settings", "loadFailed": "Failed to load settings", "webhookUrl": "Webhook URL", "webhookDesc": "This secret URL receives image push notifications from your CI pipeline.", "noWebhookUrl": "No webhook URL configured", "copy": "Copy", "copied": "Webhook URL copied to clipboard", "regenerateUrl": "Regenerate URL", "regenerating": "Regenerating...", "regenerated": "Webhook URL regenerated", "regenerateFailed": "Failed to regenerate webhook URL", "regenerateWarning": "Warning: regenerating will invalidate the current URL. Update your CI pipelines.", "sslCertificate": "SSL Certificate", "sslCertificateHelp": "Wildcard certificate from NPM for auto-SSL on proxy hosts", "selectCertificate": "Select Certificate", "noCertificate": "None (no SSL)", "clearCertificate": "Clear", "loadingCertificates": "Loading certificates...", "noCertificatesFound": "No wildcard certificates found in NPM" };
|
||||
const settingsRegistries$1 = { "title": "Container Registries", "description": "Manage your container registries for image detection.", "addRegistry": "Add Registry", "editRegistry": "Edit Registry", "addNewRegistry": "Add New Registry", "name": "Name", "nameHelp": "A friendly name for this registry", "url": "URL", "urlHelp": "Registry base URL", "type": "Type", "typeHelp": "Registry type for API compatibility", "token": "Token", "tokenHelpNew": "API token for authentication", "tokenHelpEdit": "Leave empty to keep the existing token", "owner": "Owner", "ownerHelp": "Package owners, comma-separated (e.g., alexei,my-org)", "save": "Save", "saving": "Saving...", "update": "Update", "test": "Test", "testing": "Testing...", "edit": "Edit", "delete": "Delete", "noRegistries": "No registries configured yet.", "addFirst": "Add your first registry", "registryUpdated": "Registry updated", "registryAdded": "Registry added", "registryDeleted": 'Registry "{name}" deleted', "testSuccess": 'Connection to "{name}" successful', "saveFailed": "Failed to save registry", "deleteFailed": "Failed to delete registry", "testFailed": "Connection test failed", "loadFailed": "Failed to load registries", "deleteConfirm": 'Delete registry "{name}"? This cannot be undone.' };
|
||||
const settingsCredentials$1 = { "title": "Credentials", "description": "Manage credentials for Nginx Proxy Manager and registry tokens. All values are encrypted at rest.", "npm": "Nginx Proxy Manager", "npmDesc": "Credentials for managing proxy hosts via NPM API", "configured": "Configured", "npmUrl": "NPM URL", "npmUrlHelp": "Nginx Proxy Manager API URL", "email": "Email", "emailHelp": "NPM admin email", "password": "Password", "passwordHelpNew": "NPM admin password (will be encrypted)", "passwordHelpEdit": "Enter the new password to replace the existing one", "changeCredentials": "Change Credentials", "save": "Save", "saving": "Saving...", "saved": "NPM credentials saved", "saveFailed": "Failed to save NPM credentials", "loadFailed": "Failed to load credentials", "registryTokens": "Registry Tokens", "registryTokensDesc": "Registry authentication tokens are managed per-registry in the", "registriesLink": "Registries", "registryTokensSuffix": "section. Each registry stores its token encrypted in the database." };
|
||||
const settingsAuth$1 = { "title": "Authentication Settings", "description": "Configure authentication mode and manage users.", "authMode": "Authentication Mode", "local": "Local (username/password)", "oidc": "OIDC (SSO)", "oidcConfig": "OIDC Provider Configuration", "issuerUrl": "Issuer URL", "clientId": "Client ID", "clientSecret": "Client Secret", "redirectUrl": "Redirect URL", "saveSettings": "Save Settings", "saving": "Saving...", "saved": "Settings saved", "saveFailed": "Failed to save", "loadFailed": "Failed to load settings", "localUsers": "Local Users", "username": "Username", "email": "Email", "role": "Role", "created": "Created", "noUsers": "No users found.", "addUser": "Add User", "viewer": "Viewer", "admin": "Admin", "userCreated": "User created", "userDeleted": "User deleted", "createFailed": "Failed to create user", "deleteFailed": "Failed to delete user", "deleteConfirm": "Are you sure you want to delete this user?", "usernameRequired": "Username and password are required", "password": "Password" };
|
||||
const login$1 = { "title": "Docker Watcher", "subtitle": "Sign in to your account", "username": "Username", "password": "Password", "signIn": "Sign in", "signingIn": "Signing in...", "or": "or", "ssoButton": "Sign in with SSO (OIDC)", "loginFailed": "Login failed", "networkError": "Network error" };
|
||||
const proxies$1 = { "title": "Proxies", "create": "Create Proxy", "noProxies": "No proxies configured yet.", "noProxiesDesc": "Create a standalone proxy or deploy a project to see proxies here.", "standalone": "Standalone Proxies", "managed": "Managed", "lastChecked": "Last checked", "health": { "healthy": "Healthy", "unhealthy": "Unhealthy", "unknown": "Unknown" }, "filter": { "search": "Search proxies...", "health": "Health", "type": "Type", "all": "All", "clear": "Clear filters" }, "form": { "title": "Create Proxy", "editTitle": "Edit Proxy", "destination": "Destination URL / IP", "port": "Port", "domain": "Domain", "domainHelp": "The public domain for this proxy.", "validate": "Validate", "validating": "Validating...", "create": "Create Proxy", "save": "Save Changes", "cancel": "Cancel", "delete": "Delete", "deleteConfirm": "Delete this proxy? This cannot be undone." }, "validation": { "title": "Destination Validation", "syntax": "URL syntax", "dns": "DNS resolution", "tcp": "TCP connection", "http": "HTTP response", "checking": "Checking...", "skipped": "Skipped" } };
|
||||
const common$1 = { "cancel": "Cancel", "confirm": "Confirm", "delete": "Delete", "edit": "Edit", "save": "Save", "retry": "Retry", "loading": "Loading...", "noData": "No data", "project": "Project", "back": "Back", "actions": "Actions", "stop": "Stop", "start": "Start", "restart": "Restart", "remove": "Remove", "instance": "instance", "instances": "instances" };
|
||||
const instance$1 = { "stopConfirm": "This will stop the running container. The instance can be started again later.", "restartConfirm": "This will restart the container, causing brief downtime.", "removeConfirm": "This will permanently remove the container and its proxy configuration. This cannot be undone.", "actionFailed": "Action failed" };
|
||||
const empty$1 = { "noProjects": "No projects yet", "noProjectsDesc": "Get started by creating your first project or use Quick Deploy.", "createProject": "Create Project", "noInstances": "No instances", "noInstancesDesc": "Deploy a new version to see instances here.", "noDeploys": "No deploy history", "noDeploysDesc": "Deploy history will appear here after your first deployment.", "noRegistries": "No registries", "noRegistriesDesc": "Add a container registry to enable image detection.", "noVolumes": "No volumes", "noVolumesDesc": "Configure volume mounts for persistent data.", "noUsers": "No users", "noUsersDesc": "Add local users to manage access." };
|
||||
const validation$1 = { "required": "{field} is required", "invalidUrl": "Invalid URL format", "invalidDomain": "Invalid domain format", "invalidIp": "Invalid IP format", "invalidEmail": "Invalid email format", "invalidPort": "Port must be between 1 and 65535", "invalidPollingInterval": "Polling interval must be between 10 and 86400 seconds", "invalidProjectName": "Only lowercase letters, numbers, and hyphens allowed", "requiredWhenUpdating": "{field} is required when updating credentials", "requiredForNew": "{field} is required for new registries" };
|
||||
const confirm$1 = { "stopInstance": "Stop Instance", "startInstance": "Start Instance", "restartInstance": "Restart Instance", "removeInstance": "Remove Instance" };
|
||||
const theme$1 = { "light": "Light", "dark": "Dark", "system": "System" };
|
||||
const entityPicker$1 = { "search": "Search...", "noResults": "No results found" };
|
||||
const stale$1 = { "title": "Stale Containers", "noStale": "No stale containers", "noStaleDesc": "All containers are healthy and running.", "cleanup": "Clean up", "cleanupAll": "Clean up all", "confirmCleanup": "This will stop and remove the container. Continue?", "confirmBulkCleanup": "This will stop and remove all stale containers. Continue?", "daysStale": "days stale", "lastAlive": "Last alive", "count": "Stale", "cleanedUp": "Container cleaned up", "bulkCleanedUp": "{count} containers cleaned up", "cleanupFailed": "Cleanup failed", "loadFailed": "Failed to load stale containers" };
|
||||
const events$1 = { "title": "Event Log", "noEvents": "No events found", "noEventsDesc": "Events will appear here as they occur.", "loadMore": "Load more", "newEvents": "new events", "filter": { "severity": "Severity", "source": "Source", "dateRange": "Date range", "search": "Search events...", "lastHour": "Last hour", "last24h": "Last 24 hours", "last7d": "Last 7 days", "allTime": "All time", "clear": "Clear filters" }, "severity": { "info": "Info", "warn": "Warning", "error": "Error" }, "source": { "deploy": "Deploy", "container": "Container", "proxy": "Proxy", "system": "System" }, "metadata": "Details" };
|
||||
const stats$1 = { "cpu": "CPU", "mem": "MEM", "unavailable": "Stats unavailable" };
|
||||
const systemHealth$1 = { "title": "System Health", "containers": "Containers", "proxies": "Proxies", "recentErrors": "Recent Errors" };
|
||||
const language$1 = { "en": "English", "ru": "Russian" };
|
||||
const en = {
|
||||
app: app$1,
|
||||
health: health$1,
|
||||
nav: nav$1,
|
||||
dashboard: dashboard$1,
|
||||
projects: projects$1,
|
||||
projectDetail: projectDetail$1,
|
||||
envEditor: envEditor$1,
|
||||
volumeEditor: volumeEditor$1,
|
||||
volumeBrowser: volumeBrowser$1,
|
||||
quickDeploy: quickDeploy$1,
|
||||
settings: settings$1,
|
||||
settingsGeneral: settingsGeneral$1,
|
||||
settingsRegistries: settingsRegistries$1,
|
||||
settingsCredentials: settingsCredentials$1,
|
||||
settingsAuth: settingsAuth$1,
|
||||
login: login$1,
|
||||
proxies: proxies$1,
|
||||
common: common$1,
|
||||
instance: instance$1,
|
||||
empty: empty$1,
|
||||
validation: validation$1,
|
||||
confirm: confirm$1,
|
||||
theme: theme$1,
|
||||
entityPicker: entityPicker$1,
|
||||
stale: stale$1,
|
||||
events: events$1,
|
||||
stats: stats$1,
|
||||
systemHealth: systemHealth$1,
|
||||
language: language$1
|
||||
};
|
||||
const app = { "name": "Docker Watcher", "version": "v0.1" };
|
||||
const health = { "connected": "подключён", "disconnected": "отключён", "rawError": "Технические детали", "retryNow": "Проверить сейчас" };
|
||||
const nav = { "dashboard": "Панель", "projects": "Проекты", "deploy": "Деплой", "proxies": "Прокси", "events": "События", "settings": "Настройки", "logout": "Выйти" };
|
||||
const dashboard = { "title": "Панель управления", "quickDeploy": "Быстрый деплой", "totalProjects": "Всего проектов", "runningInstances": "Запущенных экземпляров", "failedInstances": "Сбойных экземпляров", "projects": "Проекты", "retry": "Повторить", "noProjects": "Проектов пока нет.", "addFirst": "Добавьте первый проект", "loadFailed": "Не удалось загрузить панель", "staleContainers": "Устаревшие контейнеры" };
|
||||
const projects = { "title": "Проекты", "addProject": "Добавить проект", "cancel": "Отмена", "newProject": "Новый проект", "name": "Название", "image": "Образ", "port": "Порт", "registry": "Реестр", "created": "Создан", "view": "Открыть", "noProjects": "Проекты ещё не настроены.", "getStarted": "Нажмите «Добавить проект» для начала.", "createProject": "Создать проект", "creating": "Создание...", "healthcheck": "Путь проверки здоровья", "nameRequired": "Название и образ обязательны.", "loadFailed": "Не удалось загрузить проекты", "createFailed": "Не удалось создать проект", "browseImages": "Обзор образов", "selectImage": "Выберите образ", "noImages": "Образы не найдены", "loadingImages": "Загрузка образов...", "imageLoadFailed": "Не удалось загрузить образы" };
|
||||
const projectDetail = { "deleteProject": "Удалить проект", "envVars": "Переменные окружения", "volumes": "Тома", "stages": "Стадии", "noStages": "Для этого проекта не настроены стадии.", "pattern": "Шаблон", "autoDeploy": "авто-деплой", "requiresConfirm": "нужно подтверждение", "instances": "экземпляров", "deployNewVersion": "Развернуть новую версию", "selectTag": "Выберите тег для деплоя", "loadingTags": "Загрузка тегов...", "chooseTag": "Выберите тег...", "enterTag": "Введите тег образа (напр., dev-abc123)", "deploy": "Развернуть", "deploying": "Развёртывание...", "recentDeploys": "Последние деплои", "noDeployHistory": "Нет истории деплоев для этого проекта.", "tag": "Тег", "status": "Статус", "started": "Начат", "finished": "Завершён", "error": "Ошибка", "noInstancesRunning": "Нет запущенных экземпляров", "deleteConfirmTitle": "Удалить проект", "deleteConfirmMessage": "Это безвозвратно удалит проект '{name}' и все его стадии, экземпляры и историю деплоев.", "loadFailed": "Не удалось загрузить проект", "deleteFailed": "Не удалось удалить проект", "deployFailed": "Деплой не удался" };
|
||||
const envEditor = { "title": "Переменные окружения", "description": "Управление переопределениями переменных окружения на уровне стадий. Значения стадий переопределяют значения проекта.", "stage": "Стадия", "projectDefaults": "Значения проекта по умолчанию", "stageOverrides": "Переопределения стадии", "key": "Ключ", "value": "Значение", "secret": "Секрет", "source": "Источник", "actions": "Действия", "overridden": "переопределено", "inherited": "наследуется", "overridesProject": "переопределяет проект", "stageOnly": "только стадия", "edit": "Изменить", "change": "Изменить", "delete": "Удалить", "save": "Сохранить", "add": "Добавить", "adding": "Добавление...", "noStages": "Стадии не настроены. Сначала добавьте стадии к проекту.", "loadFailed": "Не удалось загрузить проект", "envAdded": "Переменная окружения добавлена", "envUpdated": "Переменная окружения обновлена", "envDeleted": "Переменная окружения удалена", "addFailed": "Не удалось добавить переменную", "updateFailed": "Не удалось обновить переменную", "deleteFailed": "Не удалось удалить переменную", "loadEnvFailed": "Не удалось загрузить переменные" };
|
||||
const volumeEditor = { "title": "Тома", "description": "Настройка монтирования томов для контейнеров. Выберите область видимости для управления общим доступом между развёртываниями.", "sourceHost": "Источник (хост)", "targetContainer": "Цель (контейнер)", "scope": "Область", "nameColumn": "Имя", "namePlaceholder": "напр. shared-db", "requiresName": "требуется имя", "noHostPath": "нет пути на хосте", "tmpfs": "tmpfs (в памяти)", "actions": "Действия", "edit": "Изменить", "delete": "Удалить", "save": "Сохранить", "add": "Добавить", "adding": "Добавление...", "noVolumes": "Тома ещё не настроены. Добавьте один выше.", "volumeAdded": "Том добавлен", "volumeUpdated": "Том обновлён", "volumeDeleted": "Том удалён", "loadFailed": "Не удалось загрузить тома", "addFailed": "Не удалось добавить том", "updateFailed": "Не удалось обновить том", "deleteFailed": "Не удалось удалить том" };
|
||||
const volumeBrowser = { "title": "Обзор тома", "loadFailed": "Не удалось загрузить каталог", "empty": "Этот каталог пуст.", "name": "Имя", "size": "Размер", "modified": "Изменён", "downloadAll": "Скачать том как ZIP", "downloadFolder": "Скачать папку как ZIP", "upload": "Загрузить файлы", "uploaded": "Загружено", "files": "файл(ов)", "uploadFailed": "Не удалось загрузить файлы", "browse": "Обзор", "download": "Скачать" };
|
||||
const quickDeploy = { "title": "Быстрый деплой", "description": "Разверните образ контейнера без настройки. Вставьте URL образа, проверьте параметры и разверните.", "step1": "1. Введите URL образа", "imageUrl": "URL образа", "imageUrlHelp": "Полный URL образа с тегом (напр., git.example.com/user/app:dev-abc123)", "inspect": "Проверить", "inspecting": "Проверка...", "step2": "2. Проверка конфигурации", "reviewDesc": "Эти параметры были обнаружены из образа. Измените при необходимости перед деплоем.", "projectName": "Имя проекта", "port": "Порт", "portHelp": "Порт контейнера (1-65535)", "healthCheckPath": "Путь проверки здоровья", "healthCheckHelp": "Необязательный HTTP-путь для проверки работоспособности", "stage": "Стадия", "development": "Разработка", "release": "Релиз", "production": "Продакшн", "stageHelp": "Стадия развёртывания для этого образа", "subdomainOverride": "Переопределение поддомена", "subdomainHelp": "Оставьте пустым для использования шаблона по умолчанию", "envVars": "Переменные окружения", "envVarsHelp": "По одной на строку, формат KEY=VALUE", "step3": "3. Развёртывание", "deployDesc": "Будет создан новый проект и контейнер будет развёрнут немедленно.", "deployBtn": "Развернуть", "inspectedSuccess": "Образ успешно проверен", "deployedSuccess": "{name} успешно развёрнут!", "inspectFailed": "Не удалось проверить образ", "deployFailed": "Развёртывание не удалось", "browseImages": "Обзор", "selectImage": "Выберите образ из реестра", "noImages": "Образы не найдены", "loadingImages": "Загрузка...", "imageLoadFailed": "Не удалось загрузить образы" };
|
||||
const settings = { "title": "Настройки", "general": "Общие", "registries": "Реестры", "credentials": "Учётные данные", "authentication": "Аутентификация", "appearance": "Внешний вид", "staleThreshold": "Порог устаревания (дни)", "staleThresholdHelp": "Контейнеры, неактивные дольше этого срока, будут помечены как устаревшие." };
|
||||
const settingsGeneral = { "title": "Общие настройки", "globalConfig": "Глобальная конфигурация", "domain": "Домен", "domainHelp": "Базовый домен для маршрутизации поддоменов", "serverIp": "IP сервера", "serverIpHelp": "Публичный IP-адрес сервера", "dockerNetwork": "Docker-сеть", "dockerNetworkHelp": "Docker-сеть для развёрнутых контейнеров", "subdomainPattern": "Шаблон поддомена", "subdomainPatternHelp": "Шаблон для автоматически генерируемых поддоменов", "pollingInterval": "Интервал опроса (секунды)", "pollingIntervalHelp": "Как часто проверять реестры на новые теги (10-86400)", "notificationUrl": "URL уведомлений", "notificationUrlHelp": "URL вебхука для уведомлений о деплоях", "saveSettings": "Сохранить настройки", "saving": "Сохранение...", "saved": "Настройки успешно сохранены", "saveFailed": "Не удалось сохранить настройки", "loadFailed": "Не удалось загрузить настройки", "webhookUrl": "URL вебхука", "webhookDesc": "Этот секретный URL получает уведомления о push-событиях из вашего CI-пайплайна.", "noWebhookUrl": "URL вебхука не настроен", "copy": "Копировать", "copied": "URL вебхука скопирован в буфер обмена", "regenerateUrl": "Перегенерировать URL", "regenerating": "Перегенерация...", "regenerated": "URL вебхука перегенерирован", "regenerateFailed": "Не удалось перегенерировать URL вебхука", "regenerateWarning": "Внимание: перегенерация сделает текущий URL недействительным. Обновите ваши CI-пайплайны.", "sslCertificate": "SSL-сертификат", "sslCertificateHelp": "Wildcard-сертификат из NPM для автоматического SSL на прокси-хостах", "selectCertificate": "Выбрать сертификат", "noCertificate": "Нет (без SSL)", "clearCertificate": "Очистить", "loadingCertificates": "Загрузка сертификатов...", "noCertificatesFound": "Wildcard-сертификаты в NPM не найдены" };
|
||||
const settingsRegistries = { "title": "Реестры контейнеров", "description": "Управление реестрами контейнеров для обнаружения образов.", "addRegistry": "Добавить реестр", "editRegistry": "Редактировать реестр", "addNewRegistry": "Добавить новый реестр", "name": "Название", "nameHelp": "Понятное название для этого реестра", "url": "URL", "urlHelp": "Базовый URL реестра", "type": "Тип", "typeHelp": "Тип реестра для совместимости API", "token": "Токен", "tokenHelpNew": "API-токен для аутентификации", "tokenHelpEdit": "Оставьте пустым, чтобы сохранить текущий токен", "owner": "Владелец", "ownerHelp": "Владельцы пакетов через запятую (напр., alexei,my-org)", "save": "Сохранить", "saving": "Сохранение...", "update": "Обновить", "test": "Тест", "testing": "Тестирование...", "edit": "Изменить", "delete": "Удалить", "noRegistries": "Реестры ещё не настроены.", "addFirst": "Добавьте первый реестр", "registryUpdated": "Реестр обновлён", "registryAdded": "Реестр добавлен", "registryDeleted": "Реестр «{name}» удалён", "testSuccess": "Подключение к «{name}» успешно", "saveFailed": "Не удалось сохранить реестр", "deleteFailed": "Не удалось удалить реестр", "testFailed": "Тест подключения не удался", "loadFailed": "Не удалось загрузить реестры", "deleteConfirm": "Удалить реестр «{name}»? Это действие необратимо." };
|
||||
const settingsCredentials = { "title": "Учётные данные", "description": "Управление учётными данными для Nginx Proxy Manager и токенами реестров. Все значения зашифрованы.", "npm": "Nginx Proxy Manager", "npmDesc": "Учётные данные для управления прокси-хостами через NPM API", "configured": "Настроено", "npmUrl": "URL NPM", "npmUrlHelp": "URL API Nginx Proxy Manager", "email": "Email", "emailHelp": "Email администратора NPM", "password": "Пароль", "passwordHelpNew": "Пароль администратора NPM (будет зашифрован)", "passwordHelpEdit": "Введите новый пароль для замены текущего", "changeCredentials": "Изменить учётные данные", "save": "Сохранить", "saving": "Сохранение...", "saved": "Учётные данные NPM сохранены", "saveFailed": "Не удалось сохранить учётные данные NPM", "loadFailed": "Не удалось загрузить учётные данные", "registryTokens": "Токены реестров", "registryTokensDesc": "Токены аутентификации реестров управляются для каждого реестра в разделе", "registriesLink": "Реестры", "registryTokensSuffix": ". Каждый реестр хранит свой токен в зашифрованном виде." };
|
||||
const settingsAuth = { "title": "Настройки аутентификации", "description": "Настройка режима аутентификации и управление пользователями.", "authMode": "Режим аутентификации", "local": "Локальный (логин/пароль)", "oidc": "OIDC (SSO)", "oidcConfig": "Конфигурация OIDC-провайдера", "issuerUrl": "URL издателя", "clientId": "ID клиента", "clientSecret": "Секрет клиента", "redirectUrl": "URL перенаправления", "saveSettings": "Сохранить настройки", "saving": "Сохранение...", "saved": "Настройки сохранены", "saveFailed": "Не удалось сохранить", "loadFailed": "Не удалось загрузить настройки", "localUsers": "Локальные пользователи", "username": "Имя пользователя", "email": "Email", "role": "Роль", "created": "Создан", "noUsers": "Пользователи не найдены.", "addUser": "Добавить пользователя", "viewer": "Наблюдатель", "admin": "Администратор", "userCreated": "Пользователь создан", "userDeleted": "Пользователь удалён", "createFailed": "Не удалось создать пользователя", "deleteFailed": "Не удалось удалить пользователя", "deleteConfirm": "Вы уверены, что хотите удалить этого пользователя?", "usernameRequired": "Имя пользователя и пароль обязательны", "password": "Пароль" };
|
||||
const login = { "title": "Docker Watcher", "subtitle": "Войдите в свой аккаунт", "username": "Имя пользователя", "password": "Пароль", "signIn": "Войти", "signingIn": "Вход...", "or": "или", "ssoButton": "Войти через SSO (OIDC)", "loginFailed": "Ошибка входа", "networkError": "Ошибка сети" };
|
||||
const proxies = { "title": "Прокси", "create": "Создать прокси", "noProxies": "Прокси ещё не настроены.", "noProxiesDesc": "Создайте автономный прокси или разверните проект, чтобы увидеть прокси здесь.", "standalone": "Автономные прокси", "managed": "Управляемые", "lastChecked": "Последняя проверка", "health": { "healthy": "Работает", "unhealthy": "Недоступен", "unknown": "Неизвестно" }, "filter": { "search": "Поиск прокси...", "health": "Здоровье", "type": "Тип", "all": "Все", "clear": "Сбросить фильтры" }, "form": { "title": "Создать прокси", "editTitle": "Редактировать прокси", "destination": "URL / IP назначения", "port": "Порт", "domain": "Домен", "domainHelp": "Публичный домен для этого прокси.", "validate": "Проверить", "validating": "Проверка...", "create": "Создать прокси", "save": "Сохранить изменения", "cancel": "Отмена", "delete": "Удалить", "deleteConfirm": "Удалить этот прокси? Это действие необратимо." }, "validation": { "title": "Проверка назначения", "syntax": "Синтаксис URL", "dns": "DNS разрешение", "tcp": "TCP подключение", "http": "HTTP ответ", "checking": "Проверка...", "skipped": "Пропущено" } };
|
||||
const common = { "cancel": "Отмена", "confirm": "Подтвердить", "delete": "Удалить", "edit": "Изменить", "save": "Сохранить", "retry": "Повторить", "loading": "Загрузка...", "noData": "Нет данных", "project": "Проект", "back": "Назад", "actions": "Действия", "stop": "Остановить", "start": "Запустить", "restart": "Перезапустить", "remove": "Удалить", "instance": "экземпляр", "instances": "экземпляров" };
|
||||
const instance = { "stopConfirm": "Контейнер будет остановлен. Экземпляр можно будет запустить снова позже.", "restartConfirm": "Контейнер будет перезапущен с кратковременным простоем.", "removeConfirm": "Контейнер и его прокси-конфигурация будут безвозвратно удалены.", "actionFailed": "Действие не удалось" };
|
||||
const empty = { "noProjects": "Проектов пока нет", "noProjectsDesc": "Начните с создания первого проекта или используйте быстрый деплой.", "createProject": "Создать проект", "noInstances": "Нет экземпляров", "noInstancesDesc": "Разверните новую версию, чтобы увидеть экземпляры здесь.", "noDeploys": "Нет истории деплоев", "noDeploysDesc": "История деплоев появится здесь после первого развёртывания.", "noRegistries": "Нет реестров", "noRegistriesDesc": "Добавьте реестр контейнеров для обнаружения образов.", "noVolumes": "Нет томов", "noVolumesDesc": "Настройте монтирование томов для постоянных данных.", "noUsers": "Нет пользователей", "noUsersDesc": "Добавьте локальных пользователей для управления доступом." };
|
||||
const validation = { "required": "Поле {field} обязательно", "invalidUrl": "Неверный формат URL", "invalidDomain": "Неверный формат домена", "invalidIp": "Неверный формат IP", "invalidEmail": "Неверный формат email", "invalidPort": "Порт должен быть от 1 до 65535", "invalidPollingInterval": "Интервал опроса должен быть от 10 до 86400 секунд", "invalidProjectName": "Допускаются только строчные буквы, цифры и дефисы", "requiredWhenUpdating": "Поле {field} обязательно при обновлении учётных данных", "requiredForNew": "Поле {field} обязательно для новых реестров" };
|
||||
const confirm = { "stopInstance": "Остановить экземпляр", "startInstance": "Запустить экземпляр", "restartInstance": "Перезапустить экземпляр", "removeInstance": "Удалить экземпляр" };
|
||||
const theme = { "light": "Светлая", "dark": "Тёмная", "system": "Системная" };
|
||||
const entityPicker = { "search": "Поиск...", "noResults": "Ничего не найдено" };
|
||||
const stale = { "title": "Устаревшие контейнеры", "noStale": "Нет устаревших контейнеров", "noStaleDesc": "Все контейнеры исправны и работают.", "cleanup": "Очистить", "cleanupAll": "Очистить все", "confirmCleanup": "Это остановит и удалит контейнер. Продолжить?", "confirmBulkCleanup": "Это остановит и удалит все устаревшие контейнеры. Продолжить?", "daysStale": "дней устарел", "lastAlive": "Последний раз жив", "count": "Устаревшие", "cleanedUp": "Контейнер очищен", "bulkCleanedUp": "{count} контейнеров очищено", "cleanupFailed": "Не удалось очистить", "loadFailed": "Не удалось загрузить устаревшие контейнеры" };
|
||||
const events = { "title": "Журнал событий", "noEvents": "Событий не найдено", "noEventsDesc": "События будут отображаться здесь по мере их возникновения.", "loadMore": "Загрузить ещё", "newEvents": "новых событий", "filter": { "severity": "Уровень", "source": "Источник", "dateRange": "Период", "search": "Поиск событий...", "lastHour": "Последний час", "last24h": "Последние 24 часа", "last7d": "Последние 7 дней", "allTime": "За всё время", "clear": "Сбросить фильтры" }, "severity": { "info": "Инфо", "warn": "Предупреждение", "error": "Ошибка" }, "source": { "deploy": "Развёртывание", "container": "Контейнер", "proxy": "Прокси", "system": "Система" }, "metadata": "Подробности" };
|
||||
const stats = { "cpu": "ЦП", "mem": "ОЗУ", "unavailable": "Статистика недоступна" };
|
||||
const systemHealth = { "title": "Состояние системы", "containers": "Контейнеры", "proxies": "Прокси", "recentErrors": "Недавние ошибки" };
|
||||
const language = { "en": "Английский", "ru": "Русский" };
|
||||
const ru = {
|
||||
app,
|
||||
health,
|
||||
nav,
|
||||
dashboard,
|
||||
projects,
|
||||
projectDetail,
|
||||
envEditor,
|
||||
volumeEditor,
|
||||
volumeBrowser,
|
||||
quickDeploy,
|
||||
settings,
|
||||
settingsGeneral,
|
||||
settingsRegistries,
|
||||
settingsCredentials,
|
||||
settingsAuth,
|
||||
login,
|
||||
proxies,
|
||||
common,
|
||||
instance,
|
||||
empty,
|
||||
validation,
|
||||
confirm,
|
||||
theme,
|
||||
entityPicker,
|
||||
stale,
|
||||
events,
|
||||
stats,
|
||||
systemHealth,
|
||||
language
|
||||
};
|
||||
const LOCALE_KEY = "dw_locale";
|
||||
const translations = { en, ru };
|
||||
function getInitialLocale() {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
const stored = localStorage.getItem(LOCALE_KEY);
|
||||
if (stored === "en" || stored === "ru") return stored;
|
||||
}
|
||||
if (typeof navigator !== "undefined") {
|
||||
const lang = navigator.language.toLowerCase();
|
||||
if (lang.startsWith("ru")) return "ru";
|
||||
}
|
||||
return "en";
|
||||
}
|
||||
const locale = writable(getInitialLocale());
|
||||
locale.subscribe((value) => {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
localStorage.setItem(LOCALE_KEY, value);
|
||||
}
|
||||
});
|
||||
function getNestedValue(obj, path) {
|
||||
const parts = path.split(".");
|
||||
let current = obj;
|
||||
for (const part of parts) {
|
||||
if (current === null || current === void 0 || typeof current !== "object") {
|
||||
return path;
|
||||
}
|
||||
current = current[part];
|
||||
}
|
||||
return typeof current === "string" ? current : path;
|
||||
}
|
||||
const t = derived(locale, ($locale) => {
|
||||
const dict = translations[$locale] ?? translations.en;
|
||||
return (key, params) => {
|
||||
let result = getNestedValue(dict, key);
|
||||
if (result === key) {
|
||||
result = getNestedValue(translations.en, key);
|
||||
}
|
||||
if (params) {
|
||||
for (const [paramKey, paramValue] of Object.entries(params)) {
|
||||
result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), paramValue);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
});
|
||||
const availableLocales = ["en", "ru"];
|
||||
export {
|
||||
availableLocales as a,
|
||||
locale as l,
|
||||
t
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
import { n as noop, m as safe_not_equal, o as subscribe_to_store, r as run_all } from "./index.js";
|
||||
const subscriber_queue = [];
|
||||
function readable(value, start) {
|
||||
return {
|
||||
subscribe: writable(value, start).subscribe
|
||||
};
|
||||
}
|
||||
function writable(value, start = noop) {
|
||||
let stop = null;
|
||||
const subscribers = /* @__PURE__ */ new Set();
|
||||
function set(new_value) {
|
||||
if (safe_not_equal(value, new_value)) {
|
||||
value = new_value;
|
||||
if (stop) {
|
||||
const run_queue = !subscriber_queue.length;
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber[1]();
|
||||
subscriber_queue.push(subscriber, value);
|
||||
}
|
||||
if (run_queue) {
|
||||
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
||||
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
||||
}
|
||||
subscriber_queue.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function update(fn) {
|
||||
set(fn(
|
||||
/** @type {T} */
|
||||
value
|
||||
));
|
||||
}
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.add(subscriber);
|
||||
if (subscribers.size === 1) {
|
||||
stop = start(set, update) || noop;
|
||||
}
|
||||
run(
|
||||
/** @type {T} */
|
||||
value
|
||||
);
|
||||
return () => {
|
||||
subscribers.delete(subscriber);
|
||||
if (subscribers.size === 0 && stop) {
|
||||
stop();
|
||||
stop = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return { set, update, subscribe };
|
||||
}
|
||||
function derived(stores, fn, initial_value) {
|
||||
const single = !Array.isArray(stores);
|
||||
const stores_array = single ? [stores] : stores;
|
||||
if (!stores_array.every(Boolean)) {
|
||||
throw new Error("derived() expects stores as input, got a falsy value");
|
||||
}
|
||||
const auto = fn.length < 2;
|
||||
return readable(initial_value, (set, update) => {
|
||||
let started = false;
|
||||
const values = [];
|
||||
let pending = 0;
|
||||
let cleanup = noop;
|
||||
const sync = () => {
|
||||
if (pending) {
|
||||
return;
|
||||
}
|
||||
cleanup();
|
||||
const result = fn(single ? values[0] : values, set, update);
|
||||
if (auto) {
|
||||
set(result);
|
||||
} else {
|
||||
cleanup = typeof result === "function" ? result : noop;
|
||||
}
|
||||
};
|
||||
const unsubscribers = stores_array.map(
|
||||
(store, i) => subscribe_to_store(
|
||||
store,
|
||||
(value) => {
|
||||
values[i] = value;
|
||||
pending &= ~(1 << i);
|
||||
if (started) {
|
||||
sync();
|
||||
}
|
||||
},
|
||||
() => {
|
||||
pending |= 1 << i;
|
||||
}
|
||||
)
|
||||
);
|
||||
started = true;
|
||||
sync();
|
||||
return function stop() {
|
||||
run_all(unsubscribers);
|
||||
cleanup();
|
||||
started = false;
|
||||
};
|
||||
});
|
||||
}
|
||||
function get(store) {
|
||||
let value;
|
||||
subscribe_to_store(store, (_) => value = _)();
|
||||
return value;
|
||||
}
|
||||
export {
|
||||
derived as d,
|
||||
get as g,
|
||||
readable as r,
|
||||
writable as w
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
import { r as root } from "./root.js";
|
||||
import "./environment.js";
|
||||
let public_env = {};
|
||||
function set_private_env(environment) {
|
||||
}
|
||||
function set_public_env(environment) {
|
||||
public_env = environment;
|
||||
}
|
||||
let read_implementation = null;
|
||||
function set_read_implementation(fn) {
|
||||
read_implementation = fn;
|
||||
}
|
||||
function set_manifest(_) {
|
||||
}
|
||||
const options = {
|
||||
app_template_contains_nonce: false,
|
||||
async: false,
|
||||
csp: { "mode": "auto", "directives": { "upgrade-insecure-requests": false, "block-all-mixed-content": false }, "reportOnly": { "upgrade-insecure-requests": false, "block-all-mixed-content": false } },
|
||||
csrf_check_origin: true,
|
||||
csrf_trusted_origins: [],
|
||||
embedded: false,
|
||||
env_public_prefix: "PUBLIC_",
|
||||
env_private_prefix: "",
|
||||
hash_routing: false,
|
||||
hooks: null,
|
||||
// added lazily, via `get_hooks`
|
||||
preload_strategy: "modulepreload",
|
||||
root,
|
||||
service_worker: false,
|
||||
service_worker_options: void 0,
|
||||
server_error_boundaries: false,
|
||||
templates: {
|
||||
app: ({ head, body, assets, nonce, env }) => '<!doctype html>\r\n<html lang="en">\r\n <head>\r\n <meta charset="utf-8" />\r\n <link rel="icon" href="' + assets + '/favicon.png" />\r\n <meta name="viewport" content="width=device-width, initial-scale=1" />\r\n ' + head + '\r\n </head>\r\n <body data-sveltekit-preload-data="hover">\r\n <div style="display: contents">' + body + "</div>\r\n </body>\r\n</html>\r\n",
|
||||
error: ({ status, message }) => '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <title>' + message + `</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
--bg: white;
|
||||
--fg: #222;
|
||||
--divider: #ccc;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Open Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 32rem;
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-weight: 200;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
top: -0.05rem;
|
||||
}
|
||||
|
||||
.message {
|
||||
border-left: 1px solid var(--divider);
|
||||
padding: 0 0 0 1rem;
|
||||
margin: 0 0 0 1rem;
|
||||
min-height: 2.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.message h1 {
|
||||
font-weight: 400;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
--bg: #222;
|
||||
--fg: #ddd;
|
||||
--divider: #666;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error">
|
||||
<span class="status">` + status + '</span>\n <div class="message">\n <h1>' + message + "</h1>\n </div>\n </div>\n </body>\n</html>\n"
|
||||
},
|
||||
version_hash: "m287x4"
|
||||
};
|
||||
async function get_hooks() {
|
||||
let handle;
|
||||
let handleFetch;
|
||||
let handleError;
|
||||
let handleValidationError;
|
||||
let init;
|
||||
let reroute;
|
||||
let transport;
|
||||
return {
|
||||
handle,
|
||||
handleFetch,
|
||||
handleError,
|
||||
handleValidationError,
|
||||
init,
|
||||
reroute,
|
||||
transport
|
||||
};
|
||||
}
|
||||
export {
|
||||
set_public_env as a,
|
||||
set_read_implementation as b,
|
||||
set_manifest as c,
|
||||
get_hooks as g,
|
||||
options as o,
|
||||
public_env as p,
|
||||
read_implementation as r,
|
||||
set_private_env as s
|
||||
};
|
||||
@@ -0,0 +1,966 @@
|
||||
import { H as HYDRATION_ERROR, C as COMMENT_NODE, p as HYDRATION_END, q as HYDRATION_START, t as HYDRATION_START_ELSE, v as get_next_sibling, w as effect_tracking, x as get, y as render_effect, z as source, A as untrack, B as increment, D as queue_micro_task, E as active_effect, F as BOUNDARY_EFFECT, G as block, I as branch, J as create_text, K as pause_effect, L as current_batch, M as move_effect, N as defer_effect, O as set_active_effect, P as set_active_reaction, Q as set_component_context, R as Batch, S as handle_error, T as active_reaction, U as component_context, V as internal_set, W as destroy_effect, X as invoke_error_boundary, Y as svelte_boundary_reset_onerror, Z as HYDRATION_START_FAILED, _ as EFFECT_TRANSPARENT, $ as EFFECT_PRESERVED, a0 as define_property, a1 as init_operations, a2 as get_first_child, a3 as hydration_failed, a4 as clear_text_content, a5 as component_root, a6 as array_from, a7 as is_passive_event, a8 as push, a9 as pop, aa as set, ab as LEGACY_PROPS, ac as flushSync, ad as mutable_source, ae as render, af as setContext, i as derived } from "./index.js";
|
||||
function hydration_mismatch(location) {
|
||||
{
|
||||
console.warn(`https://svelte.dev/e/hydration_mismatch`);
|
||||
}
|
||||
}
|
||||
function svelte_boundary_reset_noop() {
|
||||
{
|
||||
console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`);
|
||||
}
|
||||
}
|
||||
let hydrating = false;
|
||||
function set_hydrating(value) {
|
||||
hydrating = value;
|
||||
}
|
||||
let hydrate_node;
|
||||
function set_hydrate_node(node) {
|
||||
if (node === null) {
|
||||
hydration_mismatch();
|
||||
throw HYDRATION_ERROR;
|
||||
}
|
||||
return hydrate_node = node;
|
||||
}
|
||||
function hydrate_next() {
|
||||
return set_hydrate_node(get_next_sibling(hydrate_node));
|
||||
}
|
||||
function next(count = 1) {
|
||||
if (hydrating) {
|
||||
var i = count;
|
||||
var node = hydrate_node;
|
||||
while (i--) {
|
||||
node = /** @type {TemplateNode} */
|
||||
get_next_sibling(node);
|
||||
}
|
||||
hydrate_node = node;
|
||||
}
|
||||
}
|
||||
function skip_nodes(remove = true) {
|
||||
var depth = 0;
|
||||
var node = hydrate_node;
|
||||
while (true) {
|
||||
if (node.nodeType === COMMENT_NODE) {
|
||||
var data = (
|
||||
/** @type {Comment} */
|
||||
node.data
|
||||
);
|
||||
if (data === HYDRATION_END) {
|
||||
if (depth === 0) return node;
|
||||
depth -= 1;
|
||||
} else if (data === HYDRATION_START || data === HYDRATION_START_ELSE || // "[1", "[2", etc. for if blocks
|
||||
data[0] === "[" && !isNaN(Number(data.slice(1)))) {
|
||||
depth += 1;
|
||||
}
|
||||
}
|
||||
var next2 = (
|
||||
/** @type {TemplateNode} */
|
||||
get_next_sibling(node)
|
||||
);
|
||||
if (remove) node.remove();
|
||||
node = next2;
|
||||
}
|
||||
}
|
||||
function createSubscriber(start) {
|
||||
let subscribers = 0;
|
||||
let version = source(0);
|
||||
let stop;
|
||||
return () => {
|
||||
if (effect_tracking()) {
|
||||
get(version);
|
||||
render_effect(() => {
|
||||
if (subscribers === 0) {
|
||||
stop = untrack(() => start(() => increment(version)));
|
||||
}
|
||||
subscribers += 1;
|
||||
return () => {
|
||||
queue_micro_task(() => {
|
||||
subscribers -= 1;
|
||||
if (subscribers === 0) {
|
||||
stop?.();
|
||||
stop = void 0;
|
||||
increment(version);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
var flags = EFFECT_TRANSPARENT | EFFECT_PRESERVED;
|
||||
function boundary(node, props, children, transform_error) {
|
||||
new Boundary(node, props, children, transform_error);
|
||||
}
|
||||
class Boundary {
|
||||
/** @type {Boundary | null} */
|
||||
parent;
|
||||
is_pending = false;
|
||||
/**
|
||||
* API-level transformError transform function. Transforms errors before they reach the `failed` snippet.
|
||||
* Inherited from parent boundary, or defaults to identity.
|
||||
* @type {(error: unknown) => unknown}
|
||||
*/
|
||||
transform_error;
|
||||
/** @type {TemplateNode} */
|
||||
#anchor;
|
||||
/** @type {TemplateNode | null} */
|
||||
#hydrate_open = hydrating ? hydrate_node : null;
|
||||
/** @type {BoundaryProps} */
|
||||
#props;
|
||||
/** @type {((anchor: Node) => void)} */
|
||||
#children;
|
||||
/** @type {Effect} */
|
||||
#effect;
|
||||
/** @type {Effect | null} */
|
||||
#main_effect = null;
|
||||
/** @type {Effect | null} */
|
||||
#pending_effect = null;
|
||||
/** @type {Effect | null} */
|
||||
#failed_effect = null;
|
||||
/** @type {DocumentFragment | null} */
|
||||
#offscreen_fragment = null;
|
||||
#local_pending_count = 0;
|
||||
#pending_count = 0;
|
||||
#pending_count_update_queued = false;
|
||||
/** @type {Set<Effect>} */
|
||||
#dirty_effects = /* @__PURE__ */ new Set();
|
||||
/** @type {Set<Effect>} */
|
||||
#maybe_dirty_effects = /* @__PURE__ */ new Set();
|
||||
/**
|
||||
* A source containing the number of pending async deriveds/expressions.
|
||||
* Only created if `$effect.pending()` is used inside the boundary,
|
||||
* otherwise updating the source results in needless `Batch.ensure()`
|
||||
* calls followed by no-op flushes
|
||||
* @type {Source<number> | null}
|
||||
*/
|
||||
#effect_pending = null;
|
||||
#effect_pending_subscriber = createSubscriber(() => {
|
||||
this.#effect_pending = source(this.#local_pending_count);
|
||||
return () => {
|
||||
this.#effect_pending = null;
|
||||
};
|
||||
});
|
||||
/**
|
||||
* @param {TemplateNode} node
|
||||
* @param {BoundaryProps} props
|
||||
* @param {((anchor: Node) => void)} children
|
||||
* @param {((error: unknown) => unknown) | undefined} [transform_error]
|
||||
*/
|
||||
constructor(node, props, children, transform_error) {
|
||||
this.#anchor = node;
|
||||
this.#props = props;
|
||||
this.#children = (anchor) => {
|
||||
var effect = (
|
||||
/** @type {Effect} */
|
||||
active_effect
|
||||
);
|
||||
effect.b = this;
|
||||
effect.f |= BOUNDARY_EFFECT;
|
||||
children(anchor);
|
||||
};
|
||||
this.parent = /** @type {Effect} */
|
||||
active_effect.b;
|
||||
this.transform_error = transform_error ?? this.parent?.transform_error ?? ((e) => e);
|
||||
this.#effect = block(() => {
|
||||
if (hydrating) {
|
||||
const comment = (
|
||||
/** @type {Comment} */
|
||||
this.#hydrate_open
|
||||
);
|
||||
hydrate_next();
|
||||
const server_rendered_pending = comment.data === HYDRATION_START_ELSE;
|
||||
const server_rendered_failed = comment.data.startsWith(HYDRATION_START_FAILED);
|
||||
if (server_rendered_failed) {
|
||||
const serialized_error = JSON.parse(comment.data.slice(HYDRATION_START_FAILED.length));
|
||||
this.#hydrate_failed_content(serialized_error);
|
||||
} else if (server_rendered_pending) {
|
||||
this.#hydrate_pending_content();
|
||||
} else {
|
||||
this.#hydrate_resolved_content();
|
||||
}
|
||||
} else {
|
||||
this.#render();
|
||||
}
|
||||
}, flags);
|
||||
if (hydrating) {
|
||||
this.#anchor = hydrate_node;
|
||||
}
|
||||
}
|
||||
#hydrate_resolved_content() {
|
||||
try {
|
||||
this.#main_effect = branch(() => this.#children(this.#anchor));
|
||||
} catch (error) {
|
||||
this.error(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {unknown} error The deserialized error from the server's hydration comment
|
||||
*/
|
||||
#hydrate_failed_content(error) {
|
||||
const failed = this.#props.failed;
|
||||
if (!failed) return;
|
||||
this.#failed_effect = branch(() => {
|
||||
failed(
|
||||
this.#anchor,
|
||||
() => error,
|
||||
() => () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
#hydrate_pending_content() {
|
||||
const pending = this.#props.pending;
|
||||
if (!pending) return;
|
||||
this.is_pending = true;
|
||||
this.#pending_effect = branch(() => pending(this.#anchor));
|
||||
queue_micro_task(() => {
|
||||
var fragment = this.#offscreen_fragment = document.createDocumentFragment();
|
||||
var anchor = create_text();
|
||||
fragment.append(anchor);
|
||||
this.#main_effect = this.#run(() => {
|
||||
return branch(() => this.#children(anchor));
|
||||
});
|
||||
if (this.#pending_count === 0) {
|
||||
this.#anchor.before(fragment);
|
||||
this.#offscreen_fragment = null;
|
||||
pause_effect(
|
||||
/** @type {Effect} */
|
||||
this.#pending_effect,
|
||||
() => {
|
||||
this.#pending_effect = null;
|
||||
}
|
||||
);
|
||||
this.#resolve(
|
||||
/** @type {Batch} */
|
||||
current_batch
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
#render() {
|
||||
try {
|
||||
this.is_pending = this.has_pending_snippet();
|
||||
this.#pending_count = 0;
|
||||
this.#local_pending_count = 0;
|
||||
this.#main_effect = branch(() => {
|
||||
this.#children(this.#anchor);
|
||||
});
|
||||
if (this.#pending_count > 0) {
|
||||
var fragment = this.#offscreen_fragment = document.createDocumentFragment();
|
||||
move_effect(this.#main_effect, fragment);
|
||||
const pending = (
|
||||
/** @type {(anchor: Node) => void} */
|
||||
this.#props.pending
|
||||
);
|
||||
this.#pending_effect = branch(() => pending(this.#anchor));
|
||||
} else {
|
||||
this.#resolve(
|
||||
/** @type {Batch} */
|
||||
current_batch
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.error(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
#resolve(batch) {
|
||||
this.is_pending = false;
|
||||
batch.transfer_effects(this.#dirty_effects, this.#maybe_dirty_effects);
|
||||
}
|
||||
/**
|
||||
* Defer an effect inside a pending boundary until the boundary resolves
|
||||
* @param {Effect} effect
|
||||
*/
|
||||
defer_effect(effect) {
|
||||
defer_effect(effect, this.#dirty_effects, this.#maybe_dirty_effects);
|
||||
}
|
||||
/**
|
||||
* Returns `false` if the effect exists inside a boundary whose pending snippet is shown
|
||||
* @returns {boolean}
|
||||
*/
|
||||
is_rendered() {
|
||||
return !this.is_pending && (!this.parent || this.parent.is_rendered());
|
||||
}
|
||||
has_pending_snippet() {
|
||||
return !!this.#props.pending;
|
||||
}
|
||||
/**
|
||||
* @template T
|
||||
* @param {() => T} fn
|
||||
*/
|
||||
#run(fn) {
|
||||
var previous_effect = active_effect;
|
||||
var previous_reaction = active_reaction;
|
||||
var previous_ctx = component_context;
|
||||
set_active_effect(this.#effect);
|
||||
set_active_reaction(this.#effect);
|
||||
set_component_context(this.#effect.ctx);
|
||||
try {
|
||||
Batch.ensure();
|
||||
return fn();
|
||||
} catch (e) {
|
||||
handle_error(e);
|
||||
return null;
|
||||
} finally {
|
||||
set_active_effect(previous_effect);
|
||||
set_active_reaction(previous_reaction);
|
||||
set_component_context(previous_ctx);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Updates the pending count associated with the currently visible pending snippet,
|
||||
* if any, such that we can replace the snippet with content once work is done
|
||||
* @param {1 | -1} d
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
#update_pending_count(d, batch) {
|
||||
if (!this.has_pending_snippet()) {
|
||||
if (this.parent) {
|
||||
this.parent.#update_pending_count(d, batch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.#pending_count += d;
|
||||
if (this.#pending_count === 0) {
|
||||
this.#resolve(batch);
|
||||
if (this.#pending_effect) {
|
||||
pause_effect(this.#pending_effect, () => {
|
||||
this.#pending_effect = null;
|
||||
});
|
||||
}
|
||||
if (this.#offscreen_fragment) {
|
||||
this.#anchor.before(this.#offscreen_fragment);
|
||||
this.#offscreen_fragment = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Update the source that powers `$effect.pending()` inside this boundary,
|
||||
* and controls when the current `pending` snippet (if any) is removed.
|
||||
* Do not call from inside the class
|
||||
* @param {1 | -1} d
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
update_pending_count(d, batch) {
|
||||
this.#update_pending_count(d, batch);
|
||||
this.#local_pending_count += d;
|
||||
if (!this.#effect_pending || this.#pending_count_update_queued) return;
|
||||
this.#pending_count_update_queued = true;
|
||||
queue_micro_task(() => {
|
||||
this.#pending_count_update_queued = false;
|
||||
if (this.#effect_pending) {
|
||||
internal_set(this.#effect_pending, this.#local_pending_count);
|
||||
}
|
||||
});
|
||||
}
|
||||
get_effect_pending() {
|
||||
this.#effect_pending_subscriber();
|
||||
return get(
|
||||
/** @type {Source<number>} */
|
||||
this.#effect_pending
|
||||
);
|
||||
}
|
||||
/** @param {unknown} error */
|
||||
error(error) {
|
||||
var onerror = this.#props.onerror;
|
||||
let failed = this.#props.failed;
|
||||
if (!onerror && !failed) {
|
||||
throw error;
|
||||
}
|
||||
if (this.#main_effect) {
|
||||
destroy_effect(this.#main_effect);
|
||||
this.#main_effect = null;
|
||||
}
|
||||
if (this.#pending_effect) {
|
||||
destroy_effect(this.#pending_effect);
|
||||
this.#pending_effect = null;
|
||||
}
|
||||
if (this.#failed_effect) {
|
||||
destroy_effect(this.#failed_effect);
|
||||
this.#failed_effect = null;
|
||||
}
|
||||
if (hydrating) {
|
||||
set_hydrate_node(
|
||||
/** @type {TemplateNode} */
|
||||
this.#hydrate_open
|
||||
);
|
||||
next();
|
||||
set_hydrate_node(skip_nodes());
|
||||
}
|
||||
var did_reset = false;
|
||||
var calling_on_error = false;
|
||||
const reset = () => {
|
||||
if (did_reset) {
|
||||
svelte_boundary_reset_noop();
|
||||
return;
|
||||
}
|
||||
did_reset = true;
|
||||
if (calling_on_error) {
|
||||
svelte_boundary_reset_onerror();
|
||||
}
|
||||
if (this.#failed_effect !== null) {
|
||||
pause_effect(this.#failed_effect, () => {
|
||||
this.#failed_effect = null;
|
||||
});
|
||||
}
|
||||
this.#run(() => {
|
||||
this.#render();
|
||||
});
|
||||
};
|
||||
const handle_error_result = (transformed_error) => {
|
||||
try {
|
||||
calling_on_error = true;
|
||||
onerror?.(transformed_error, reset);
|
||||
calling_on_error = false;
|
||||
} catch (error2) {
|
||||
invoke_error_boundary(error2, this.#effect && this.#effect.parent);
|
||||
}
|
||||
if (failed) {
|
||||
this.#failed_effect = this.#run(() => {
|
||||
try {
|
||||
return branch(() => {
|
||||
var effect = (
|
||||
/** @type {Effect} */
|
||||
active_effect
|
||||
);
|
||||
effect.b = this;
|
||||
effect.f |= BOUNDARY_EFFECT;
|
||||
failed(
|
||||
this.#anchor,
|
||||
() => transformed_error,
|
||||
() => reset
|
||||
);
|
||||
});
|
||||
} catch (error2) {
|
||||
invoke_error_boundary(
|
||||
error2,
|
||||
/** @type {Effect} */
|
||||
this.#effect.parent
|
||||
);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
queue_micro_task(() => {
|
||||
var result;
|
||||
try {
|
||||
result = this.transform_error(error);
|
||||
} catch (e) {
|
||||
invoke_error_boundary(e, this.#effect && this.#effect.parent);
|
||||
return;
|
||||
}
|
||||
if (result !== null && typeof result === "object" && typeof /** @type {any} */
|
||||
result.then === "function") {
|
||||
result.then(
|
||||
handle_error_result,
|
||||
/** @param {unknown} e */
|
||||
(e) => invoke_error_boundary(e, this.#effect && this.#effect.parent)
|
||||
);
|
||||
} else {
|
||||
handle_error_result(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
const event_symbol = Symbol("events");
|
||||
const all_registered_events = /* @__PURE__ */ new Set();
|
||||
const root_event_handles = /* @__PURE__ */ new Set();
|
||||
let last_propagated_event = null;
|
||||
function handle_event_propagation(event) {
|
||||
var handler_element = this;
|
||||
var owner_document = (
|
||||
/** @type {Node} */
|
||||
handler_element.ownerDocument
|
||||
);
|
||||
var event_name = event.type;
|
||||
var path = event.composedPath?.() || [];
|
||||
var current_target = (
|
||||
/** @type {null | Element} */
|
||||
path[0] || event.target
|
||||
);
|
||||
last_propagated_event = event;
|
||||
var path_idx = 0;
|
||||
var handled_at = last_propagated_event === event && event[event_symbol];
|
||||
if (handled_at) {
|
||||
var at_idx = path.indexOf(handled_at);
|
||||
if (at_idx !== -1 && (handler_element === document || handler_element === /** @type {any} */
|
||||
window)) {
|
||||
event[event_symbol] = handler_element;
|
||||
return;
|
||||
}
|
||||
var handler_idx = path.indexOf(handler_element);
|
||||
if (handler_idx === -1) {
|
||||
return;
|
||||
}
|
||||
if (at_idx <= handler_idx) {
|
||||
path_idx = at_idx;
|
||||
}
|
||||
}
|
||||
current_target = /** @type {Element} */
|
||||
path[path_idx] || event.target;
|
||||
if (current_target === handler_element) return;
|
||||
define_property(event, "currentTarget", {
|
||||
configurable: true,
|
||||
get() {
|
||||
return current_target || owner_document;
|
||||
}
|
||||
});
|
||||
var previous_reaction = active_reaction;
|
||||
var previous_effect = active_effect;
|
||||
set_active_reaction(null);
|
||||
set_active_effect(null);
|
||||
try {
|
||||
var throw_error;
|
||||
var other_errors = [];
|
||||
while (current_target !== null) {
|
||||
var parent_element = current_target.assignedSlot || current_target.parentNode || /** @type {any} */
|
||||
current_target.host || null;
|
||||
try {
|
||||
var delegated = current_target[event_symbol]?.[event_name];
|
||||
if (delegated != null && (!/** @type {any} */
|
||||
current_target.disabled || // DOM could've been updated already by the time this is reached, so we check this as well
|
||||
// -> the target could not have been disabled because it emits the event in the first place
|
||||
event.target === current_target)) {
|
||||
delegated.call(current_target, event);
|
||||
}
|
||||
} catch (error) {
|
||||
if (throw_error) {
|
||||
other_errors.push(error);
|
||||
} else {
|
||||
throw_error = error;
|
||||
}
|
||||
}
|
||||
if (event.cancelBubble || parent_element === handler_element || parent_element === null) {
|
||||
break;
|
||||
}
|
||||
current_target = parent_element;
|
||||
}
|
||||
if (throw_error) {
|
||||
for (let error of other_errors) {
|
||||
queueMicrotask(() => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
throw throw_error;
|
||||
}
|
||||
} finally {
|
||||
event[event_symbol] = handler_element;
|
||||
delete event.currentTarget;
|
||||
set_active_reaction(previous_reaction);
|
||||
set_active_effect(previous_effect);
|
||||
}
|
||||
}
|
||||
function assign_nodes(start, end) {
|
||||
var effect = (
|
||||
/** @type {Effect} */
|
||||
active_effect
|
||||
);
|
||||
if (effect.nodes === null) {
|
||||
effect.nodes = { start, end, a: null, t: null };
|
||||
}
|
||||
}
|
||||
function mount(component, options) {
|
||||
return _mount(component, options);
|
||||
}
|
||||
function hydrate(component, options) {
|
||||
init_operations();
|
||||
options.intro = options.intro ?? false;
|
||||
const target = options.target;
|
||||
const was_hydrating = hydrating;
|
||||
const previous_hydrate_node = hydrate_node;
|
||||
try {
|
||||
var anchor = get_first_child(target);
|
||||
while (anchor && (anchor.nodeType !== COMMENT_NODE || /** @type {Comment} */
|
||||
anchor.data !== HYDRATION_START)) {
|
||||
anchor = get_next_sibling(anchor);
|
||||
}
|
||||
if (!anchor) {
|
||||
throw HYDRATION_ERROR;
|
||||
}
|
||||
set_hydrating(true);
|
||||
set_hydrate_node(
|
||||
/** @type {Comment} */
|
||||
anchor
|
||||
);
|
||||
const instance = _mount(component, { ...options, anchor });
|
||||
set_hydrating(false);
|
||||
return (
|
||||
/** @type {Exports} */
|
||||
instance
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.split("\n").some((line) => line.startsWith("https://svelte.dev/e/"))) {
|
||||
throw error;
|
||||
}
|
||||
if (error !== HYDRATION_ERROR) {
|
||||
console.warn("Failed to hydrate: ", error);
|
||||
}
|
||||
if (options.recover === false) {
|
||||
hydration_failed();
|
||||
}
|
||||
init_operations();
|
||||
clear_text_content(target);
|
||||
set_hydrating(false);
|
||||
return mount(component, options);
|
||||
} finally {
|
||||
set_hydrating(was_hydrating);
|
||||
set_hydrate_node(previous_hydrate_node);
|
||||
}
|
||||
}
|
||||
const listeners = /* @__PURE__ */ new Map();
|
||||
function _mount(Component, { target, anchor, props = {}, events, context, intro = true, transformError }) {
|
||||
init_operations();
|
||||
var component = void 0;
|
||||
var unmount2 = component_root(() => {
|
||||
var anchor_node = anchor ?? target.appendChild(create_text());
|
||||
boundary(
|
||||
/** @type {TemplateNode} */
|
||||
anchor_node,
|
||||
{
|
||||
pending: () => {
|
||||
}
|
||||
},
|
||||
(anchor_node2) => {
|
||||
push({});
|
||||
var ctx = (
|
||||
/** @type {ComponentContext} */
|
||||
component_context
|
||||
);
|
||||
if (context) ctx.c = context;
|
||||
if (events) {
|
||||
props.$$events = events;
|
||||
}
|
||||
if (hydrating) {
|
||||
assign_nodes(
|
||||
/** @type {TemplateNode} */
|
||||
anchor_node2,
|
||||
null
|
||||
);
|
||||
}
|
||||
component = Component(anchor_node2, props) || {};
|
||||
if (hydrating) {
|
||||
active_effect.nodes.end = hydrate_node;
|
||||
if (hydrate_node === null || hydrate_node.nodeType !== COMMENT_NODE || /** @type {Comment} */
|
||||
hydrate_node.data !== HYDRATION_END) {
|
||||
hydration_mismatch();
|
||||
throw HYDRATION_ERROR;
|
||||
}
|
||||
}
|
||||
pop();
|
||||
},
|
||||
transformError
|
||||
);
|
||||
var registered_events = /* @__PURE__ */ new Set();
|
||||
var event_handle = (events2) => {
|
||||
for (var i = 0; i < events2.length; i++) {
|
||||
var event_name = events2[i];
|
||||
if (registered_events.has(event_name)) continue;
|
||||
registered_events.add(event_name);
|
||||
var passive = is_passive_event(event_name);
|
||||
for (const node of [target, document]) {
|
||||
var counts = listeners.get(node);
|
||||
if (counts === void 0) {
|
||||
counts = /* @__PURE__ */ new Map();
|
||||
listeners.set(node, counts);
|
||||
}
|
||||
var count = counts.get(event_name);
|
||||
if (count === void 0) {
|
||||
node.addEventListener(event_name, handle_event_propagation, { passive });
|
||||
counts.set(event_name, 1);
|
||||
} else {
|
||||
counts.set(event_name, count + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
event_handle(array_from(all_registered_events));
|
||||
root_event_handles.add(event_handle);
|
||||
return () => {
|
||||
for (var event_name of registered_events) {
|
||||
for (const node of [target, document]) {
|
||||
var counts = (
|
||||
/** @type {Map<string, number>} */
|
||||
listeners.get(node)
|
||||
);
|
||||
var count = (
|
||||
/** @type {number} */
|
||||
counts.get(event_name)
|
||||
);
|
||||
if (--count == 0) {
|
||||
node.removeEventListener(event_name, handle_event_propagation);
|
||||
counts.delete(event_name);
|
||||
if (counts.size === 0) {
|
||||
listeners.delete(node);
|
||||
}
|
||||
} else {
|
||||
counts.set(event_name, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
root_event_handles.delete(event_handle);
|
||||
if (anchor_node !== anchor) {
|
||||
anchor_node.parentNode?.removeChild(anchor_node);
|
||||
}
|
||||
};
|
||||
});
|
||||
mounted_components.set(component, unmount2);
|
||||
return component;
|
||||
}
|
||||
let mounted_components = /* @__PURE__ */ new WeakMap();
|
||||
function unmount(component, options) {
|
||||
const fn = mounted_components.get(component);
|
||||
if (fn) {
|
||||
mounted_components.delete(component);
|
||||
return fn(options);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
function asClassComponent$1(component) {
|
||||
return class extends Svelte4Component {
|
||||
/** @param {any} options */
|
||||
constructor(options) {
|
||||
super({
|
||||
component,
|
||||
...options
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
class Svelte4Component {
|
||||
/** @type {any} */
|
||||
#events;
|
||||
/** @type {Record<string, any>} */
|
||||
#instance;
|
||||
/**
|
||||
* @param {ComponentConstructorOptions & {
|
||||
* component: any;
|
||||
* }} options
|
||||
*/
|
||||
constructor(options) {
|
||||
var sources = /* @__PURE__ */ new Map();
|
||||
var add_source = (key, value) => {
|
||||
var s = mutable_source(value, false, false);
|
||||
sources.set(key, s);
|
||||
return s;
|
||||
};
|
||||
const props = new Proxy(
|
||||
{ ...options.props || {}, $$events: {} },
|
||||
{
|
||||
get(target, prop) {
|
||||
return get(sources.get(prop) ?? add_source(prop, Reflect.get(target, prop)));
|
||||
},
|
||||
has(target, prop) {
|
||||
if (prop === LEGACY_PROPS) return true;
|
||||
get(sources.get(prop) ?? add_source(prop, Reflect.get(target, prop)));
|
||||
return Reflect.has(target, prop);
|
||||
},
|
||||
set(target, prop, value) {
|
||||
set(sources.get(prop) ?? add_source(prop, value), value);
|
||||
return Reflect.set(target, prop, value);
|
||||
}
|
||||
}
|
||||
);
|
||||
this.#instance = (options.hydrate ? hydrate : mount)(options.component, {
|
||||
target: options.target,
|
||||
anchor: options.anchor,
|
||||
props,
|
||||
context: options.context,
|
||||
intro: options.intro ?? false,
|
||||
recover: options.recover,
|
||||
transformError: options.transformError
|
||||
});
|
||||
if (!options?.props?.$$host || options.sync === false) {
|
||||
flushSync();
|
||||
}
|
||||
this.#events = props.$$events;
|
||||
for (const key of Object.keys(this.#instance)) {
|
||||
if (key === "$set" || key === "$destroy" || key === "$on") continue;
|
||||
define_property(this, key, {
|
||||
get() {
|
||||
return this.#instance[key];
|
||||
},
|
||||
/** @param {any} value */
|
||||
set(value) {
|
||||
this.#instance[key] = value;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
this.#instance.$set = /** @param {Record<string, any>} next */
|
||||
(next2) => {
|
||||
Object.assign(props, next2);
|
||||
};
|
||||
this.#instance.$destroy = () => {
|
||||
unmount(this.#instance);
|
||||
};
|
||||
}
|
||||
/** @param {Record<string, any>} props */
|
||||
$set(props) {
|
||||
this.#instance.$set(props);
|
||||
}
|
||||
/**
|
||||
* @param {string} event
|
||||
* @param {(...args: any[]) => any} callback
|
||||
* @returns {any}
|
||||
*/
|
||||
$on(event, callback) {
|
||||
this.#events[event] = this.#events[event] || [];
|
||||
const cb = (...args) => callback.call(this, ...args);
|
||||
this.#events[event].push(cb);
|
||||
return () => {
|
||||
this.#events[event] = this.#events[event].filter(
|
||||
/** @param {any} fn */
|
||||
(fn) => fn !== cb
|
||||
);
|
||||
};
|
||||
}
|
||||
$destroy() {
|
||||
this.#instance.$destroy();
|
||||
}
|
||||
}
|
||||
function asClassComponent(component) {
|
||||
const component_constructor = asClassComponent$1(component);
|
||||
const _render = (props, { context, csp, transformError } = {}) => {
|
||||
const result = render(component, { props, context, csp, transformError });
|
||||
const munged = Object.defineProperties(
|
||||
/** @type {LegacyRenderResult & PromiseLike<LegacyRenderResult>} */
|
||||
{},
|
||||
{
|
||||
css: {
|
||||
value: { code: "", map: null }
|
||||
},
|
||||
head: {
|
||||
get: () => result.head
|
||||
},
|
||||
html: {
|
||||
get: () => result.body
|
||||
},
|
||||
then: {
|
||||
/**
|
||||
* this is not type-safe, but honestly it's the best I can do right now, and it's a straightforward function.
|
||||
*
|
||||
* @template TResult1
|
||||
* @template [TResult2=never]
|
||||
* @param { (value: LegacyRenderResult) => TResult1 } onfulfilled
|
||||
* @param { (reason: unknown) => TResult2 } onrejected
|
||||
*/
|
||||
value: (onfulfilled, onrejected) => {
|
||||
{
|
||||
const user_result = onfulfilled({
|
||||
css: munged.css,
|
||||
head: munged.head,
|
||||
html: munged.html
|
||||
});
|
||||
return Promise.resolve(user_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return munged;
|
||||
};
|
||||
component_constructor.render = _render;
|
||||
return component_constructor;
|
||||
}
|
||||
function Root($$renderer, $$props) {
|
||||
$$renderer.component(($$renderer2) => {
|
||||
let {
|
||||
stores,
|
||||
page,
|
||||
constructors,
|
||||
components = [],
|
||||
form,
|
||||
data_0 = null,
|
||||
data_1 = null,
|
||||
data_2 = null
|
||||
} = $$props;
|
||||
{
|
||||
setContext("__svelte__", stores);
|
||||
}
|
||||
{
|
||||
stores.page.set(page);
|
||||
}
|
||||
const Pyramid_2 = derived(() => constructors[2]);
|
||||
if (constructors[1]) {
|
||||
$$renderer2.push("<!--[0-->");
|
||||
const Pyramid_0 = constructors[0];
|
||||
if (Pyramid_0) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
Pyramid_0($$renderer2, {
|
||||
data: data_0,
|
||||
form,
|
||||
params: page.params,
|
||||
children: ($$renderer3) => {
|
||||
if (constructors[2]) {
|
||||
$$renderer3.push("<!--[0-->");
|
||||
const Pyramid_1 = constructors[1];
|
||||
if (Pyramid_1) {
|
||||
$$renderer3.push("<!--[-->");
|
||||
Pyramid_1($$renderer3, {
|
||||
data: data_1,
|
||||
form,
|
||||
params: page.params,
|
||||
children: ($$renderer4) => {
|
||||
if (Pyramid_2()) {
|
||||
$$renderer4.push("<!--[-->");
|
||||
Pyramid_2()($$renderer4, { data: data_2, form, params: page.params });
|
||||
$$renderer4.push("<!--]-->");
|
||||
} else {
|
||||
$$renderer4.push("<!--[!-->");
|
||||
$$renderer4.push("<!--]-->");
|
||||
}
|
||||
},
|
||||
$$slots: { default: true }
|
||||
});
|
||||
$$renderer3.push("<!--]-->");
|
||||
} else {
|
||||
$$renderer3.push("<!--[!-->");
|
||||
$$renderer3.push("<!--]-->");
|
||||
}
|
||||
} else {
|
||||
$$renderer3.push("<!--[-1-->");
|
||||
const Pyramid_1 = constructors[1];
|
||||
if (Pyramid_1) {
|
||||
$$renderer3.push("<!--[-->");
|
||||
Pyramid_1($$renderer3, { data: data_1, form, params: page.params });
|
||||
$$renderer3.push("<!--]-->");
|
||||
} else {
|
||||
$$renderer3.push("<!--[!-->");
|
||||
$$renderer3.push("<!--]-->");
|
||||
}
|
||||
}
|
||||
$$renderer3.push(`<!--]-->`);
|
||||
},
|
||||
$$slots: { default: true }
|
||||
});
|
||||
$$renderer2.push("<!--]-->");
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
$$renderer2.push("<!--]-->");
|
||||
}
|
||||
} else {
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
const Pyramid_0 = constructors[0];
|
||||
if (Pyramid_0) {
|
||||
$$renderer2.push("<!--[-->");
|
||||
Pyramid_0($$renderer2, { data: data_0, form, params: page.params });
|
||||
$$renderer2.push("<!--]-->");
|
||||
} else {
|
||||
$$renderer2.push("<!--[!-->");
|
||||
$$renderer2.push("<!--]-->");
|
||||
}
|
||||
}
|
||||
$$renderer2.push(`<!--]--> `);
|
||||
{
|
||||
$$renderer2.push("<!--[-1-->");
|
||||
}
|
||||
$$renderer2.push(`<!--]-->`);
|
||||
});
|
||||
}
|
||||
const root = asClassComponent(Root);
|
||||
export {
|
||||
root as r
|
||||
};
|
||||
@@ -0,0 +1,789 @@
|
||||
import { json, text } from "@sveltejs/kit";
|
||||
import { SvelteKitError, HttpError } from "@sveltejs/kit/internal";
|
||||
import { with_request_store } from "@sveltejs/kit/internal/server";
|
||||
import * as devalue from "devalue";
|
||||
import { t as text_decoder, b as base64_encode, a as base64_decode } from "./utils.js";
|
||||
const SVELTE_KIT_ASSETS = "/_svelte_kit_assets";
|
||||
const ENDPOINT_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"];
|
||||
const MUTATIVE_METHODS = ["POST", "PUT", "PATCH", "DELETE"];
|
||||
const PAGE_METHODS = ["GET", "POST", "HEAD"];
|
||||
function set_nested_value(object, path_string, value) {
|
||||
if (path_string.startsWith("n:")) {
|
||||
path_string = path_string.slice(2);
|
||||
value = value === "" ? void 0 : parseFloat(value);
|
||||
} else if (path_string.startsWith("b:")) {
|
||||
path_string = path_string.slice(2);
|
||||
value = value === "on";
|
||||
}
|
||||
deep_set(object, split_path(path_string), value);
|
||||
}
|
||||
function convert_formdata(data) {
|
||||
const result = {};
|
||||
for (let key of data.keys()) {
|
||||
const is_array = key.endsWith("[]");
|
||||
let values = data.getAll(key);
|
||||
if (is_array) key = key.slice(0, -2);
|
||||
if (values.length > 1 && !is_array) {
|
||||
throw new Error(`Form cannot contain duplicated keys — "${key}" has ${values.length} values`);
|
||||
}
|
||||
values = values.filter(
|
||||
(entry) => typeof entry === "string" || entry.name !== "" || entry.size > 0
|
||||
);
|
||||
if (key.startsWith("n:")) {
|
||||
key = key.slice(2);
|
||||
values = values.map((v) => v === "" ? void 0 : parseFloat(
|
||||
/** @type {string} */
|
||||
v
|
||||
));
|
||||
} else if (key.startsWith("b:")) {
|
||||
key = key.slice(2);
|
||||
values = values.map((v) => v === "on");
|
||||
}
|
||||
set_nested_value(result, key, is_array ? values : values[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const BINARY_FORM_CONTENT_TYPE = "application/x-sveltekit-formdata";
|
||||
const BINARY_FORM_VERSION = 0;
|
||||
const HEADER_BYTES = 1 + 4 + 2;
|
||||
async function deserialize_binary_form(request) {
|
||||
if (request.headers.get("content-type") !== BINARY_FORM_CONTENT_TYPE) {
|
||||
const form_data = await request.formData();
|
||||
return { data: convert_formdata(form_data), meta: {}, form_data };
|
||||
}
|
||||
if (!request.body) {
|
||||
throw deserialize_error("no body");
|
||||
}
|
||||
const content_length = parseInt(request.headers.get("content-length") ?? "");
|
||||
if (Number.isNaN(content_length)) {
|
||||
throw deserialize_error("invalid Content-Length header");
|
||||
}
|
||||
const reader = request.body.getReader();
|
||||
const chunks = [];
|
||||
function get_chunk(index) {
|
||||
if (index in chunks) return chunks[index];
|
||||
let i = chunks.length;
|
||||
while (i <= index) {
|
||||
chunks[i] = reader.read().then((chunk) => chunk.value);
|
||||
i++;
|
||||
}
|
||||
return chunks[index];
|
||||
}
|
||||
async function get_buffer(offset, length) {
|
||||
let start_chunk;
|
||||
let chunk_start = 0;
|
||||
let chunk_index;
|
||||
for (chunk_index = 0; ; chunk_index++) {
|
||||
const chunk = await get_chunk(chunk_index);
|
||||
if (!chunk) return null;
|
||||
const chunk_end = chunk_start + chunk.byteLength;
|
||||
if (offset >= chunk_start && offset < chunk_end) {
|
||||
start_chunk = chunk;
|
||||
break;
|
||||
}
|
||||
chunk_start = chunk_end;
|
||||
}
|
||||
if (offset + length <= chunk_start + start_chunk.byteLength) {
|
||||
return start_chunk.subarray(offset - chunk_start, offset + length - chunk_start);
|
||||
}
|
||||
const chunks2 = [start_chunk.subarray(offset - chunk_start)];
|
||||
let cursor = start_chunk.byteLength - offset + chunk_start;
|
||||
while (cursor < length) {
|
||||
chunk_index++;
|
||||
let chunk = await get_chunk(chunk_index);
|
||||
if (!chunk) return null;
|
||||
if (chunk.byteLength > length - cursor) {
|
||||
chunk = chunk.subarray(0, length - cursor);
|
||||
}
|
||||
chunks2.push(chunk);
|
||||
cursor += chunk.byteLength;
|
||||
}
|
||||
const buffer = new Uint8Array(length);
|
||||
cursor = 0;
|
||||
for (const chunk of chunks2) {
|
||||
buffer.set(chunk, cursor);
|
||||
cursor += chunk.byteLength;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
const header = await get_buffer(0, HEADER_BYTES);
|
||||
if (!header) throw deserialize_error("too short");
|
||||
if (header[0] !== BINARY_FORM_VERSION) {
|
||||
throw deserialize_error(`got version ${header[0]}, expected version ${BINARY_FORM_VERSION}`);
|
||||
}
|
||||
const header_view = new DataView(header.buffer, header.byteOffset, header.byteLength);
|
||||
const data_length = header_view.getUint32(1, true);
|
||||
if (HEADER_BYTES + data_length > content_length) {
|
||||
throw deserialize_error("data overflow");
|
||||
}
|
||||
const file_offsets_length = header_view.getUint16(5, true);
|
||||
if (HEADER_BYTES + data_length + file_offsets_length > content_length) {
|
||||
throw deserialize_error("file offset table overflow");
|
||||
}
|
||||
const data_buffer = await get_buffer(HEADER_BYTES, data_length);
|
||||
if (!data_buffer) throw deserialize_error("data too short");
|
||||
let file_offsets;
|
||||
let files_start_offset;
|
||||
if (file_offsets_length > 0) {
|
||||
const file_offsets_buffer = await get_buffer(HEADER_BYTES + data_length, file_offsets_length);
|
||||
if (!file_offsets_buffer) throw deserialize_error("file offset table too short");
|
||||
const parsed_offsets = JSON.parse(text_decoder.decode(file_offsets_buffer));
|
||||
if (!Array.isArray(parsed_offsets) || parsed_offsets.some((n) => typeof n !== "number" || !Number.isInteger(n) || n < 0)) {
|
||||
throw deserialize_error("invalid file offset table");
|
||||
}
|
||||
file_offsets = /** @type {Array<number>} */
|
||||
parsed_offsets;
|
||||
files_start_offset = HEADER_BYTES + data_length + file_offsets_length;
|
||||
}
|
||||
const file_spans = [];
|
||||
const [data, meta] = devalue.parse(text_decoder.decode(data_buffer), {
|
||||
File: ([name, type, size, last_modified, index]) => {
|
||||
if (typeof name !== "string" || typeof type !== "string" || typeof size !== "number" || typeof last_modified !== "number" || typeof index !== "number") {
|
||||
throw deserialize_error("invalid file metadata");
|
||||
}
|
||||
let offset = file_offsets[index];
|
||||
if (offset === void 0) {
|
||||
throw deserialize_error("duplicate file offset table index");
|
||||
}
|
||||
file_offsets[index] = void 0;
|
||||
offset += files_start_offset;
|
||||
if (offset + size > content_length) {
|
||||
throw deserialize_error("file data overflow");
|
||||
}
|
||||
file_spans.push({ offset, size });
|
||||
return new Proxy(new LazyFile(name, type, size, last_modified, get_chunk, offset), {
|
||||
getPrototypeOf() {
|
||||
return File.prototype;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
file_spans.sort((a, b) => a.offset - b.offset || a.size - b.size);
|
||||
for (let i = 1; i < file_spans.length; i++) {
|
||||
const previous = file_spans[i - 1];
|
||||
const current = file_spans[i];
|
||||
const previous_end = previous.offset + previous.size;
|
||||
if (previous_end < current.offset) {
|
||||
throw deserialize_error("gaps in file data");
|
||||
}
|
||||
if (previous_end > current.offset) {
|
||||
throw deserialize_error("overlapping file data");
|
||||
}
|
||||
}
|
||||
void (async () => {
|
||||
let has_more = true;
|
||||
while (has_more) {
|
||||
const chunk = await get_chunk(chunks.length);
|
||||
has_more = !!chunk;
|
||||
}
|
||||
})();
|
||||
return { data, meta, form_data: null };
|
||||
}
|
||||
function deserialize_error(message) {
|
||||
return new SvelteKitError(400, "Bad Request", `Could not deserialize binary form: ${message}`);
|
||||
}
|
||||
class LazyFile {
|
||||
/** @type {(index: number) => Promise<Uint8Array<ArrayBuffer> | undefined>} */
|
||||
#get_chunk;
|
||||
/** @type {number} */
|
||||
#offset;
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {string} type
|
||||
* @param {number} size
|
||||
* @param {number} last_modified
|
||||
* @param {(index: number) => Promise<Uint8Array<ArrayBuffer> | undefined>} get_chunk
|
||||
* @param {number} offset
|
||||
*/
|
||||
constructor(name, type, size, last_modified, get_chunk, offset) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.size = size;
|
||||
this.lastModified = last_modified;
|
||||
this.webkitRelativePath = "";
|
||||
this.#get_chunk = get_chunk;
|
||||
this.#offset = offset;
|
||||
this.arrayBuffer = this.arrayBuffer.bind(this);
|
||||
this.bytes = this.bytes.bind(this);
|
||||
this.slice = this.slice.bind(this);
|
||||
this.stream = this.stream.bind(this);
|
||||
this.text = this.text.bind(this);
|
||||
}
|
||||
/** @type {ArrayBuffer | undefined} */
|
||||
#buffer;
|
||||
async arrayBuffer() {
|
||||
this.#buffer ??= await new Response(this.stream()).arrayBuffer();
|
||||
return this.#buffer;
|
||||
}
|
||||
async bytes() {
|
||||
return new Uint8Array(await this.arrayBuffer());
|
||||
}
|
||||
/**
|
||||
* @param {number=} start
|
||||
* @param {number=} end
|
||||
* @param {string=} contentType
|
||||
*/
|
||||
slice(start = 0, end = this.size, contentType = this.type) {
|
||||
if (start < 0) {
|
||||
start = Math.max(this.size + start, 0);
|
||||
} else {
|
||||
start = Math.min(start, this.size);
|
||||
}
|
||||
if (end < 0) {
|
||||
end = Math.max(this.size + end, 0);
|
||||
} else {
|
||||
end = Math.min(end, this.size);
|
||||
}
|
||||
const size = Math.max(end - start, 0);
|
||||
const file = new LazyFile(
|
||||
this.name,
|
||||
contentType,
|
||||
size,
|
||||
this.lastModified,
|
||||
this.#get_chunk,
|
||||
this.#offset + start
|
||||
);
|
||||
return file;
|
||||
}
|
||||
stream() {
|
||||
let cursor = 0;
|
||||
let chunk_index = 0;
|
||||
return new ReadableStream({
|
||||
start: async (controller) => {
|
||||
let chunk_start = 0;
|
||||
let start_chunk;
|
||||
for (chunk_index = 0; ; chunk_index++) {
|
||||
const chunk = await this.#get_chunk(chunk_index);
|
||||
if (!chunk) return null;
|
||||
const chunk_end = chunk_start + chunk.byteLength;
|
||||
if (this.#offset >= chunk_start && this.#offset < chunk_end) {
|
||||
start_chunk = chunk;
|
||||
break;
|
||||
}
|
||||
chunk_start = chunk_end;
|
||||
}
|
||||
if (this.#offset + this.size <= chunk_start + start_chunk.byteLength) {
|
||||
controller.enqueue(
|
||||
start_chunk.subarray(this.#offset - chunk_start, this.#offset + this.size - chunk_start)
|
||||
);
|
||||
controller.close();
|
||||
} else {
|
||||
controller.enqueue(start_chunk.subarray(this.#offset - chunk_start));
|
||||
cursor = start_chunk.byteLength - this.#offset + chunk_start;
|
||||
}
|
||||
},
|
||||
pull: async (controller) => {
|
||||
chunk_index++;
|
||||
let chunk = await this.#get_chunk(chunk_index);
|
||||
if (!chunk) {
|
||||
controller.error("incomplete file data");
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
if (chunk.byteLength > this.size - cursor) {
|
||||
chunk = chunk.subarray(0, this.size - cursor);
|
||||
}
|
||||
controller.enqueue(chunk);
|
||||
cursor += chunk.byteLength;
|
||||
if (cursor >= this.size) {
|
||||
controller.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
async text() {
|
||||
return text_decoder.decode(await this.arrayBuffer());
|
||||
}
|
||||
}
|
||||
const path_regex = /^[a-zA-Z_$]\w*(\.[a-zA-Z_$]\w*|\[\d+\])*$/;
|
||||
function split_path(path) {
|
||||
if (!path_regex.test(path)) {
|
||||
throw new Error(`Invalid path ${path}`);
|
||||
}
|
||||
return path.split(/\.|\[|\]/).filter(Boolean);
|
||||
}
|
||||
function check_prototype_pollution(key) {
|
||||
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
||||
throw new Error(
|
||||
`Invalid key "${key}"`
|
||||
);
|
||||
}
|
||||
}
|
||||
function deep_set(object, keys, value) {
|
||||
let current = object;
|
||||
for (let i = 0; i < keys.length - 1; i += 1) {
|
||||
const key = keys[i];
|
||||
check_prototype_pollution(key);
|
||||
const is_array = /^\d+$/.test(keys[i + 1]);
|
||||
const exists = Object.hasOwn(current, key);
|
||||
const inner = current[key];
|
||||
if (exists && is_array !== Array.isArray(inner)) {
|
||||
throw new Error(`Invalid array key ${keys[i + 1]}`);
|
||||
}
|
||||
if (!exists) {
|
||||
current[key] = is_array ? [] : {};
|
||||
}
|
||||
current = current[key];
|
||||
}
|
||||
const final_key = keys[keys.length - 1];
|
||||
check_prototype_pollution(final_key);
|
||||
current[final_key] = value;
|
||||
}
|
||||
function normalize_issue(issue, server = false) {
|
||||
const normalized = { name: "", path: [], message: issue.message, server };
|
||||
if (issue.path !== void 0) {
|
||||
let name = "";
|
||||
for (const segment of issue.path) {
|
||||
const key = (
|
||||
/** @type {string | number} */
|
||||
typeof segment === "object" ? segment.key : segment
|
||||
);
|
||||
normalized.path.push(key);
|
||||
if (typeof key === "number") {
|
||||
name += `[${key}]`;
|
||||
} else if (typeof key === "string") {
|
||||
name += name === "" ? key : "." + key;
|
||||
}
|
||||
}
|
||||
normalized.name = name;
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
function flatten_issues(issues) {
|
||||
const result = {};
|
||||
for (const issue of issues) {
|
||||
(result.$ ??= []).push(issue);
|
||||
let name = "";
|
||||
if (issue.path !== void 0) {
|
||||
for (const key of issue.path) {
|
||||
if (typeof key === "number") {
|
||||
name += `[${key}]`;
|
||||
} else if (typeof key === "string") {
|
||||
name += name === "" ? key : "." + key;
|
||||
}
|
||||
(result[name] ??= []).push(issue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function deep_get(object, path) {
|
||||
let current = object;
|
||||
for (const key of path) {
|
||||
if (current == null || typeof current !== "object") {
|
||||
return current;
|
||||
}
|
||||
current = current[key];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
function create_field_proxy(target, get_input, set_input, get_issues, path = []) {
|
||||
const get_value = () => {
|
||||
return deep_get(get_input(), path);
|
||||
};
|
||||
return new Proxy(target, {
|
||||
get(target2, prop) {
|
||||
if (typeof prop === "symbol") return target2[prop];
|
||||
if (/^\d+$/.test(prop)) {
|
||||
return create_field_proxy({}, get_input, set_input, get_issues, [
|
||||
...path,
|
||||
parseInt(prop, 10)
|
||||
]);
|
||||
}
|
||||
const key = build_path_string(path);
|
||||
if (prop === "set") {
|
||||
const set_func = function(newValue) {
|
||||
set_input(path, newValue);
|
||||
return newValue;
|
||||
};
|
||||
return create_field_proxy(set_func, get_input, set_input, get_issues, [...path, prop]);
|
||||
}
|
||||
if (prop === "value") {
|
||||
return create_field_proxy(get_value, get_input, set_input, get_issues, [...path, prop]);
|
||||
}
|
||||
if (prop === "issues" || prop === "allIssues") {
|
||||
const issues_func = () => {
|
||||
const all_issues = get_issues()[key === "" ? "$" : key];
|
||||
if (prop === "allIssues") {
|
||||
return all_issues?.map((issue) => ({
|
||||
path: issue.path,
|
||||
message: issue.message
|
||||
}));
|
||||
}
|
||||
return all_issues?.filter((issue) => issue.name === key)?.map((issue) => ({
|
||||
path: issue.path,
|
||||
message: issue.message
|
||||
}));
|
||||
};
|
||||
return create_field_proxy(issues_func, get_input, set_input, get_issues, [...path, prop]);
|
||||
}
|
||||
if (prop === "as") {
|
||||
const as_func = (type, input_value) => {
|
||||
const is_array = type === "file multiple" || type === "select multiple" || type === "checkbox" && typeof input_value === "string";
|
||||
const prefix = type === "number" || type === "range" ? "n:" : type === "checkbox" && !is_array ? "b:" : "";
|
||||
const base_props = {
|
||||
name: prefix + key + (is_array ? "[]" : ""),
|
||||
get "aria-invalid"() {
|
||||
const issues = get_issues();
|
||||
return key in issues ? "true" : void 0;
|
||||
}
|
||||
};
|
||||
if (type !== "text" && type !== "select" && type !== "select multiple") {
|
||||
base_props.type = type === "file multiple" ? "file" : type;
|
||||
}
|
||||
if (type === "submit" || type === "hidden") {
|
||||
return Object.defineProperties(base_props, {
|
||||
value: { value: input_value, enumerable: true }
|
||||
});
|
||||
}
|
||||
if (type === "select" || type === "select multiple") {
|
||||
return Object.defineProperties(base_props, {
|
||||
multiple: { value: is_array, enumerable: true },
|
||||
value: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return get_value();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (type === "checkbox" || type === "radio") {
|
||||
return Object.defineProperties(base_props, {
|
||||
value: { value: input_value ?? "on", enumerable: true },
|
||||
checked: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
const value = get_value();
|
||||
if (type === "radio") {
|
||||
return value === input_value;
|
||||
}
|
||||
if (is_array) {
|
||||
return (value ?? []).includes(input_value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (type === "file" || type === "file multiple") {
|
||||
return Object.defineProperties(base_props, {
|
||||
multiple: { value: is_array, enumerable: true },
|
||||
files: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
const value = get_value();
|
||||
if (value instanceof File) {
|
||||
if (typeof DataTransfer !== "undefined") {
|
||||
const fileList = new DataTransfer();
|
||||
fileList.items.add(value);
|
||||
return fileList.files;
|
||||
}
|
||||
return { 0: value, length: 1 };
|
||||
}
|
||||
if (Array.isArray(value) && value.every((f) => f instanceof File)) {
|
||||
if (typeof DataTransfer !== "undefined") {
|
||||
const fileList = new DataTransfer();
|
||||
value.forEach((file) => fileList.items.add(file));
|
||||
return fileList.files;
|
||||
}
|
||||
const fileListLike = { length: value.length };
|
||||
value.forEach((file, index) => {
|
||||
fileListLike[index] = file;
|
||||
});
|
||||
return fileListLike;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return Object.defineProperties(base_props, {
|
||||
value: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
const value = get_value();
|
||||
return value != null ? String(value) : "";
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
return create_field_proxy(as_func, get_input, set_input, get_issues, [...path, "as"]);
|
||||
}
|
||||
return create_field_proxy({}, get_input, set_input, get_issues, [...path, prop]);
|
||||
}
|
||||
});
|
||||
}
|
||||
function build_path_string(path) {
|
||||
let result = "";
|
||||
for (const segment of path) {
|
||||
if (typeof segment === "number") {
|
||||
result += `[${segment}]`;
|
||||
} else {
|
||||
result += result === "" ? segment : "." + segment;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function negotiate(accept, types) {
|
||||
const parts = [];
|
||||
accept.split(",").forEach((str, i) => {
|
||||
const match = /([^/ \t]+)\/([^; \t]+)[ \t]*(?:;[ \t]*q=([0-9.]+))?/.exec(str);
|
||||
if (match) {
|
||||
const [, type, subtype, q = "1"] = match;
|
||||
parts.push({ type, subtype, q: +q, i });
|
||||
}
|
||||
});
|
||||
parts.sort((a, b) => {
|
||||
if (a.q !== b.q) {
|
||||
return b.q - a.q;
|
||||
}
|
||||
if (a.subtype === "*" !== (b.subtype === "*")) {
|
||||
return a.subtype === "*" ? 1 : -1;
|
||||
}
|
||||
if (a.type === "*" !== (b.type === "*")) {
|
||||
return a.type === "*" ? 1 : -1;
|
||||
}
|
||||
return a.i - b.i;
|
||||
});
|
||||
let accepted;
|
||||
let min_priority = Infinity;
|
||||
for (const mimetype of types) {
|
||||
const [type, subtype] = mimetype.split("/");
|
||||
const priority = parts.findIndex(
|
||||
(part) => (part.type === type || part.type === "*") && (part.subtype === subtype || part.subtype === "*")
|
||||
);
|
||||
if (priority !== -1 && priority < min_priority) {
|
||||
accepted = mimetype;
|
||||
min_priority = priority;
|
||||
}
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
function is_content_type(request, ...types) {
|
||||
const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? "";
|
||||
return types.includes(type.toLowerCase());
|
||||
}
|
||||
function is_form_content_type(request) {
|
||||
return is_content_type(
|
||||
request,
|
||||
"application/x-www-form-urlencoded",
|
||||
"multipart/form-data",
|
||||
"text/plain",
|
||||
BINARY_FORM_CONTENT_TYPE
|
||||
);
|
||||
}
|
||||
function coalesce_to_error(err) {
|
||||
return err instanceof Error || err && /** @type {any} */
|
||||
err.name && /** @type {any} */
|
||||
err.message ? (
|
||||
/** @type {Error} */
|
||||
err
|
||||
) : new Error(JSON.stringify(err));
|
||||
}
|
||||
function normalize_error(error) {
|
||||
return (
|
||||
/** @type {import('../exports/internal/index.js').Redirect | HttpError | SvelteKitError | Error} */
|
||||
error
|
||||
);
|
||||
}
|
||||
function get_status(error) {
|
||||
return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500;
|
||||
}
|
||||
function get_message(error) {
|
||||
return error instanceof SvelteKitError ? error.text : "Internal Error";
|
||||
}
|
||||
const escape_html_attr_dict = {
|
||||
"&": "&",
|
||||
'"': """
|
||||
// Svelte also escapes < because the escape function could be called inside a `noscript` there
|
||||
// https://github.com/sveltejs/svelte/security/advisories/GHSA-8266-84wp-wv5c
|
||||
// However, that doesn't apply in SvelteKit
|
||||
};
|
||||
const escape_html_dict = {
|
||||
"&": "&",
|
||||
"<": "<"
|
||||
};
|
||||
const surrogates = (
|
||||
// high surrogate without paired low surrogate
|
||||
"[\\ud800-\\udbff](?![\\udc00-\\udfff])|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\udc00-\\udfff]"
|
||||
);
|
||||
const escape_html_attr_regex = new RegExp(
|
||||
`[${Object.keys(escape_html_attr_dict).join("")}]|` + surrogates,
|
||||
"g"
|
||||
);
|
||||
const escape_html_regex = new RegExp(
|
||||
`[${Object.keys(escape_html_dict).join("")}]|` + surrogates,
|
||||
"g"
|
||||
);
|
||||
function escape_html(str, is_attr) {
|
||||
const dict = is_attr ? escape_html_attr_dict : escape_html_dict;
|
||||
const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => {
|
||||
if (match.length === 2) {
|
||||
return match;
|
||||
}
|
||||
return dict[match] ?? `&#${match.charCodeAt(0)};`;
|
||||
});
|
||||
return escaped_str;
|
||||
}
|
||||
function method_not_allowed(mod, method) {
|
||||
return text(`${method} method not allowed`, {
|
||||
status: 405,
|
||||
headers: {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
|
||||
// "The server must generate an Allow header field in a 405 status code response"
|
||||
allow: allowed_methods(mod).join(", ")
|
||||
}
|
||||
});
|
||||
}
|
||||
function allowed_methods(mod) {
|
||||
const allowed = ENDPOINT_METHODS.filter((method) => method in mod);
|
||||
if ("GET" in mod && !("HEAD" in mod)) {
|
||||
allowed.push("HEAD");
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
function get_global_name(options) {
|
||||
return `__sveltekit_${options.version_hash}`;
|
||||
}
|
||||
function static_error_page(options, status, message) {
|
||||
let page = options.templates.error({ status, message: escape_html(message) });
|
||||
return text(page, {
|
||||
headers: { "content-type": "text/html; charset=utf-8" },
|
||||
status
|
||||
});
|
||||
}
|
||||
async function handle_fatal_error(event, state, options, error) {
|
||||
error = error instanceof HttpError ? error : coalesce_to_error(error);
|
||||
const status = get_status(error);
|
||||
const body = await handle_error_and_jsonify(event, state, options, error);
|
||||
const type = negotiate(event.request.headers.get("accept") || "text/html", [
|
||||
"application/json",
|
||||
"text/html"
|
||||
]);
|
||||
if (event.isDataRequest || type === "application/json") {
|
||||
return json(body, {
|
||||
status
|
||||
});
|
||||
}
|
||||
return static_error_page(options, status, body.message);
|
||||
}
|
||||
async function handle_error_and_jsonify(event, state, options, error) {
|
||||
if (error instanceof HttpError) {
|
||||
return { message: "Unknown Error", ...error.body };
|
||||
}
|
||||
const status = get_status(error);
|
||||
const message = get_message(error);
|
||||
return await with_request_store(
|
||||
{ event, state },
|
||||
() => options.hooks.handleError({ error, event, status, message })
|
||||
) ?? { message };
|
||||
}
|
||||
function redirect_response(status, location) {
|
||||
const response = new Response(void 0, {
|
||||
status,
|
||||
headers: { location }
|
||||
});
|
||||
return response;
|
||||
}
|
||||
function clarify_devalue_error(event, error) {
|
||||
if (error.path) {
|
||||
return `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (${error.path}). If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#Universal-hooks-transport.`;
|
||||
}
|
||||
if (error.path === "") {
|
||||
return `Data returned from \`load\` while rendering ${event.route.id} is not a plain object`;
|
||||
}
|
||||
return error.message;
|
||||
}
|
||||
function serialize_uses(node) {
|
||||
const uses = {};
|
||||
if (node.uses && node.uses.dependencies.size > 0) {
|
||||
uses.dependencies = Array.from(node.uses.dependencies);
|
||||
}
|
||||
if (node.uses && node.uses.search_params.size > 0) {
|
||||
uses.search_params = Array.from(node.uses.search_params);
|
||||
}
|
||||
if (node.uses && node.uses.params.size > 0) {
|
||||
uses.params = Array.from(node.uses.params);
|
||||
}
|
||||
if (node.uses?.parent) uses.parent = 1;
|
||||
if (node.uses?.route) uses.route = 1;
|
||||
if (node.uses?.url) uses.url = 1;
|
||||
return uses;
|
||||
}
|
||||
function has_prerendered_path(manifest, pathname) {
|
||||
return manifest._.prerendered_routes.has(pathname) || pathname.at(-1) === "/" && manifest._.prerendered_routes.has(pathname.slice(0, -1));
|
||||
}
|
||||
function format_server_error(status, error, event) {
|
||||
const formatted_text = `
|
||||
\x1B[1;31m[${status}] ${event.request.method} ${event.url.pathname}\x1B[0m`;
|
||||
if (status === 404) {
|
||||
return formatted_text;
|
||||
}
|
||||
return `${formatted_text}
|
||||
${error.stack}`;
|
||||
}
|
||||
function get_node_type(node_id) {
|
||||
const parts = node_id?.split("/");
|
||||
const filename = parts?.at(-1);
|
||||
if (!filename) return "unknown";
|
||||
const dot_parts = filename.split(".");
|
||||
return dot_parts.slice(0, -1).join(".");
|
||||
}
|
||||
const INVALIDATED_PARAM = "x-sveltekit-invalidated";
|
||||
const TRAILING_SLASH_PARAM = "x-sveltekit-trailing-slash";
|
||||
function stringify(data, transport) {
|
||||
const encoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.encode]));
|
||||
return devalue.stringify(data, encoders);
|
||||
}
|
||||
function stringify_remote_arg(value, transport) {
|
||||
if (value === void 0) return "";
|
||||
const json_string = stringify(value, transport);
|
||||
const bytes = new TextEncoder().encode(json_string);
|
||||
return base64_encode(bytes).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
|
||||
}
|
||||
function parse_remote_arg(string, transport) {
|
||||
if (!string) return void 0;
|
||||
const json_string = text_decoder.decode(
|
||||
// no need to add back `=` characters, atob can handle it
|
||||
base64_decode(string.replaceAll("-", "+").replaceAll("_", "/"))
|
||||
);
|
||||
const decoders = Object.fromEntries(Object.entries(transport).map(([k, v]) => [k, v.decode]));
|
||||
return devalue.parse(json_string, decoders);
|
||||
}
|
||||
function create_remote_key(id, payload) {
|
||||
return id + "/" + payload;
|
||||
}
|
||||
export {
|
||||
ENDPOINT_METHODS as E,
|
||||
INVALIDATED_PARAM as I,
|
||||
MUTATIVE_METHODS as M,
|
||||
PAGE_METHODS as P,
|
||||
SVELTE_KIT_ASSETS as S,
|
||||
TRAILING_SLASH_PARAM as T,
|
||||
set_nested_value as a,
|
||||
stringify as b,
|
||||
create_field_proxy as c,
|
||||
deep_set as d,
|
||||
create_remote_key as e,
|
||||
flatten_issues as f,
|
||||
negotiate as g,
|
||||
handle_error_and_jsonify as h,
|
||||
get_status as i,
|
||||
is_form_content_type as j,
|
||||
normalize_error as k,
|
||||
get_global_name as l,
|
||||
method_not_allowed as m,
|
||||
normalize_issue as n,
|
||||
serialize_uses as o,
|
||||
clarify_devalue_error as p,
|
||||
get_node_type as q,
|
||||
escape_html as r,
|
||||
stringify_remote_arg as s,
|
||||
static_error_page as t,
|
||||
redirect_response as u,
|
||||
parse_remote_arg as v,
|
||||
deserialize_binary_form as w,
|
||||
has_prerendered_path as x,
|
||||
handle_fatal_error as y,
|
||||
format_server_error as z
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import "clsx";
|
||||
import { n as noop } from "./index.js";
|
||||
import "./exports.js";
|
||||
import "@sveltejs/kit/internal/server";
|
||||
import "./root.js";
|
||||
const is_legacy = noop.toString().includes("$$") || /function \w+\(\) \{\}/.test(noop.toString());
|
||||
const placeholder_url = "a:";
|
||||
if (is_legacy) {
|
||||
({
|
||||
data: {},
|
||||
form: null,
|
||||
error: null,
|
||||
params: {},
|
||||
route: { id: null },
|
||||
state: {},
|
||||
status: -1,
|
||||
url: new URL(placeholder_url)
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { j as getContext } from "./index.js";
|
||||
import "clsx";
|
||||
import "@sveltejs/kit/internal";
|
||||
import "./exports.js";
|
||||
import "./utils.js";
|
||||
import "@sveltejs/kit/internal/server";
|
||||
import "./root.js";
|
||||
import "./state.svelte.js";
|
||||
const getStores = () => {
|
||||
const stores$1 = getContext("__svelte__");
|
||||
return {
|
||||
/** @type {typeof page} */
|
||||
page: {
|
||||
subscribe: stores$1.page.subscribe
|
||||
},
|
||||
/** @type {typeof navigating} */
|
||||
navigating: {
|
||||
subscribe: stores$1.navigating.subscribe
|
||||
},
|
||||
/** @type {typeof updated} */
|
||||
updated: stores$1.updated
|
||||
};
|
||||
};
|
||||
const page = {
|
||||
subscribe(fn) {
|
||||
const store = getStores().page;
|
||||
return store.subscribe(fn);
|
||||
}
|
||||
};
|
||||
export {
|
||||
page as p
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { w as writable, d as derived } from "./index3.js";
|
||||
const THEME_KEY = "dw_theme";
|
||||
function getInitialMode() {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
const stored = localStorage.getItem(THEME_KEY);
|
||||
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
||||
}
|
||||
return "system";
|
||||
}
|
||||
const themeMode = writable(getInitialMode());
|
||||
themeMode.subscribe((value) => {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
localStorage.setItem(THEME_KEY, value);
|
||||
}
|
||||
});
|
||||
derived(themeMode, ($mode) => {
|
||||
if ($mode === "system") {
|
||||
if (typeof window !== "undefined") {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
return "light";
|
||||
}
|
||||
return $mode;
|
||||
});
|
||||
export {
|
||||
themeMode as t
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import { w as writable } from "./index3.js";
|
||||
function createToastStore() {
|
||||
const { subscribe, update } = writable([]);
|
||||
let counter = 0;
|
||||
function add(message, type = "info", duration = 5e3) {
|
||||
const id = `toast-${++counter}-${Date.now()}`;
|
||||
const toast = { id, message, type, duration };
|
||||
update((toasts2) => [...toasts2, toast]);
|
||||
if (duration > 0) {
|
||||
setTimeout(() => remove(id), duration);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
function remove(id) {
|
||||
update((toasts2) => toasts2.filter((t) => t.id !== id));
|
||||
}
|
||||
function success(message, duration = 5e3) {
|
||||
return add(message, "success", duration);
|
||||
}
|
||||
function error(message, duration = 7e3) {
|
||||
return add(message, "error", duration);
|
||||
}
|
||||
function warning(message, duration = 5e3) {
|
||||
return add(message, "warning", duration);
|
||||
}
|
||||
function info(message, duration = 5e3) {
|
||||
return add(message, "info", duration);
|
||||
}
|
||||
return {
|
||||
subscribe,
|
||||
add,
|
||||
remove,
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
info
|
||||
};
|
||||
}
|
||||
const toasts = createToastStore();
|
||||
export {
|
||||
toasts as t
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
const text_encoder = new TextEncoder();
|
||||
const text_decoder = new TextDecoder();
|
||||
function get_relative_path(from, to) {
|
||||
const from_parts = from.split(/[/\\]/);
|
||||
const to_parts = to.split(/[/\\]/);
|
||||
from_parts.pop();
|
||||
while (from_parts[0] === to_parts[0]) {
|
||||
from_parts.shift();
|
||||
to_parts.shift();
|
||||
}
|
||||
let i = from_parts.length;
|
||||
while (i--) from_parts[i] = "..";
|
||||
return from_parts.concat(to_parts).join("/");
|
||||
}
|
||||
function base64_encode(bytes) {
|
||||
if (globalThis.Buffer) {
|
||||
return globalThis.Buffer.from(bytes).toString("base64");
|
||||
}
|
||||
let binary = "";
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
function base64_decode(encoded) {
|
||||
if (globalThis.Buffer) {
|
||||
const buffer = globalThis.Buffer.from(encoded, "base64");
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
const binary = atob(encoded);
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
export {
|
||||
base64_decode as a,
|
||||
base64_encode as b,
|
||||
text_encoder as c,
|
||||
get_relative_path as g,
|
||||
text_decoder as t
|
||||
};
|
||||
Reference in New Issue
Block a user