diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..2aa8c99a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,144 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.*
+!.env.example
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+.output
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+.cache
+
+# Sveltekit cache directory
+.svelte-kit/
+
+# vitepress build output
+**/.vitepress/dist
+
+# vitepress cache directory
+**/.vitepress/cache
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# Firebase cache directory
+.firebase/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# pnpm
+.pnpm-store
+
+# yarn v3
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+
+# Vite files
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
+.vite/
diff --git a/.nuxt/dev/index.mjs b/.nuxt/dev/index.mjs
deleted file mode 100644
index 588d5bd9..00000000
--- a/.nuxt/dev/index.mjs
+++ /dev/null
@@ -1,3497 +0,0 @@
-import process from 'node:process';globalThis._importMeta_={url:import.meta.url,env:process.env};import { tmpdir } from 'node:os';
-import { defineEventHandler, handleCacheHeaders, splitCookiesString, createEvent, fetchWithEvent, isEvent, eventHandler, setHeaders, sendRedirect, proxyRequest, getRequestHeader, setResponseHeaders, setResponseStatus, send, getRequestHeaders, setResponseHeader, appendResponseHeader, getRequestURL, getResponseHeader, removeResponseHeader, createError, getRequestIP, setHeader, getQuery as getQuery$1, readBody, createApp, createRouter as createRouter$1, toNodeListener, lazyEventHandler, getResponseStatus, getRouterParam, getResponseStatusText } from 'file:///home/bennet/source/vat-api/node_modules/h3/dist/index.mjs';
-import { Server } from 'node:http';
-import { resolve, dirname, join } from 'node:path';
-import nodeCrypto from 'node:crypto';
-import { parentPort, threadId } from 'node:worker_threads';
-import { escapeHtml } from 'file:///home/bennet/source/vat-api/node_modules/@vue/shared/dist/shared.cjs.js';
-import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file:///home/bennet/source/vat-api/node_modules/vue-bundle-renderer/dist/runtime.mjs';
-import { parseURL, withoutBase, joinURL, getQuery, withQuery, withTrailingSlash, decodePath, withLeadingSlash, withoutTrailingSlash, joinRelativeURL } from 'file:///home/bennet/source/vat-api/node_modules/ufo/dist/index.mjs';
-import destr, { destr as destr$1 } from 'file:///home/bennet/source/vat-api/node_modules/destr/dist/index.mjs';
-import { createHooks } from 'file:///home/bennet/source/vat-api/node_modules/hookable/dist/index.mjs';
-import { createFetch, Headers as Headers$1 } from 'file:///home/bennet/source/vat-api/node_modules/ofetch/dist/node.mjs';
-import { fetchNodeRequestHandler, callNodeRequestHandler } from 'file:///home/bennet/source/vat-api/node_modules/node-mock-http/dist/index.mjs';
-import { createStorage, prefixStorage } from 'file:///home/bennet/source/vat-api/node_modules/unstorage/dist/index.mjs';
-import unstorage_47drivers_47fs from 'file:///home/bennet/source/vat-api/node_modules/unstorage/drivers/fs.mjs';
-import { digest } from 'file:///home/bennet/source/vat-api/node_modules/ohash/dist/index.mjs';
-import { klona } from 'file:///home/bennet/source/vat-api/node_modules/klona/dist/index.mjs';
-import defu, { defuFn } from 'file:///home/bennet/source/vat-api/node_modules/defu/dist/defu.mjs';
-import { snakeCase } from 'file:///home/bennet/source/vat-api/node_modules/scule/dist/index.mjs';
-import { getContext } from 'file:///home/bennet/source/vat-api/node_modules/unctx/dist/index.mjs';
-import { toRouteMatcher, createRouter } from 'file:///home/bennet/source/vat-api/node_modules/radix3/dist/index.mjs';
-import { readFile } from 'node:fs/promises';
-import consola, { consola as consola$1 } from 'file:///home/bennet/source/vat-api/node_modules/consola/dist/index.mjs';
-import { ErrorParser } from 'file:///home/bennet/source/vat-api/node_modules/youch-core/build/index.js';
-import { Youch } from 'file:///home/bennet/source/vat-api/node_modules/youch/build/index.js';
-import { SourceMapConsumer } from 'file:///home/bennet/source/vat-api/node_modules/source-map/source-map.js';
-import { AsyncLocalStorage } from 'node:async_hooks';
-import { stringify, uneval } from 'file:///home/bennet/source/vat-api/node_modules/devalue/index.js';
-import { captureRawStackTrace, parseRawStackTrace } from 'file:///home/bennet/source/vat-api/node_modules/errx/dist/index.js';
-import { isVNode, isRef, toValue } from 'file:///home/bennet/source/vat-api/node_modules/vue/index.mjs';
-import { promises } from 'node:fs';
-import { fileURLToPath } from 'node:url';
-import { dirname as dirname$1, resolve as resolve$1 } from 'file:///home/bennet/source/vat-api/node_modules/pathe/dist/index.mjs';
-import { createHead as createHead$1, propsToString, renderSSRHead } from 'file:///home/bennet/source/vat-api/node_modules/unhead/dist/server.mjs';
-import { renderToString } from 'file:///home/bennet/source/vat-api/node_modules/vue/server-renderer/index.mjs';
-import { walkResolver } from 'file:///home/bennet/source/vat-api/node_modules/unhead/dist/utils.mjs';
-
-const serverAssets = [{"baseName":"server","dir":"/home/bennet/source/vat-api/server/assets"}];
-
-const assets$1 = createStorage();
-
-for (const asset of serverAssets) {
- assets$1.mount(asset.baseName, unstorage_47drivers_47fs({ base: asset.dir, ignore: (asset?.ignore || []) }));
-}
-
-const storage = createStorage({});
-
-storage.mount('/assets', assets$1);
-
-storage.mount('root', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/home/bennet/source/vat-api","watchOptions":{"ignored":[null]}}));
-storage.mount('src', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/home/bennet/source/vat-api/server","watchOptions":{"ignored":[null]}}));
-storage.mount('build', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/home/bennet/source/vat-api/.nuxt"}));
-storage.mount('cache', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/home/bennet/source/vat-api/.nuxt/cache"}));
-storage.mount('data', unstorage_47drivers_47fs({"driver":"fs","base":"/home/bennet/source/vat-api/.data/kv"}));
-
-function useStorage(base = "") {
- return base ? prefixStorage(storage, base) : storage;
-}
-
-const Hasher = /* @__PURE__ */ (() => {
- class Hasher2 {
- buff = "";
- #context = /* @__PURE__ */ new Map();
- write(str) {
- this.buff += str;
- }
- dispatch(value) {
- const type = value === null ? "null" : typeof value;
- return this[type](value);
- }
- object(object) {
- if (object && typeof object.toJSON === "function") {
- return this.object(object.toJSON());
- }
- const objString = Object.prototype.toString.call(object);
- let objType = "";
- const objectLength = objString.length;
- objType = objectLength < 10 ? "unknown:[" + objString + "]" : objString.slice(8, objectLength - 1);
- objType = objType.toLowerCase();
- let objectNumber = null;
- if ((objectNumber = this.#context.get(object)) === void 0) {
- this.#context.set(object, this.#context.size);
- } else {
- return this.dispatch("[CIRCULAR:" + objectNumber + "]");
- }
- if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
- this.write("buffer:");
- return this.write(object.toString("utf8"));
- }
- if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
- if (this[objType]) {
- this[objType](object);
- } else {
- this.unknown(object, objType);
- }
- } else {
- const keys = Object.keys(object).sort();
- const extraKeys = [];
- this.write("object:" + (keys.length + extraKeys.length) + ":");
- const dispatchForKey = (key) => {
- this.dispatch(key);
- this.write(":");
- this.dispatch(object[key]);
- this.write(",");
- };
- for (const key of keys) {
- dispatchForKey(key);
- }
- for (const key of extraKeys) {
- dispatchForKey(key);
- }
- }
- }
- array(arr, unordered) {
- unordered = unordered === void 0 ? false : unordered;
- this.write("array:" + arr.length + ":");
- if (!unordered || arr.length <= 1) {
- for (const entry of arr) {
- this.dispatch(entry);
- }
- return;
- }
- const contextAdditions = /* @__PURE__ */ new Map();
- const entries = arr.map((entry) => {
- const hasher = new Hasher2();
- hasher.dispatch(entry);
- for (const [key, value] of hasher.#context) {
- contextAdditions.set(key, value);
- }
- return hasher.toString();
- });
- this.#context = contextAdditions;
- entries.sort();
- return this.array(entries, false);
- }
- date(date) {
- return this.write("date:" + date.toJSON());
- }
- symbol(sym) {
- return this.write("symbol:" + sym.toString());
- }
- unknown(value, type) {
- this.write(type);
- if (!value) {
- return;
- }
- this.write(":");
- if (value && typeof value.entries === "function") {
- return this.array(
- [...value.entries()],
- true
- /* ordered */
- );
- }
- }
- error(err) {
- return this.write("error:" + err.toString());
- }
- boolean(bool) {
- return this.write("bool:" + bool);
- }
- string(string) {
- this.write("string:" + string.length + ":");
- this.write(string);
- }
- function(fn) {
- this.write("fn:");
- if (isNativeFunction(fn)) {
- this.dispatch("[native]");
- } else {
- this.dispatch(fn.toString());
- }
- }
- number(number) {
- return this.write("number:" + number);
- }
- null() {
- return this.write("Null");
- }
- undefined() {
- return this.write("Undefined");
- }
- regexp(regex) {
- return this.write("regex:" + regex.toString());
- }
- arraybuffer(arr) {
- this.write("arraybuffer:");
- return this.dispatch(new Uint8Array(arr));
- }
- url(url) {
- return this.write("url:" + url.toString());
- }
- map(map) {
- this.write("map:");
- const arr = [...map];
- return this.array(arr, false);
- }
- set(set) {
- this.write("set:");
- const arr = [...set];
- return this.array(arr, false);
- }
- bigint(number) {
- return this.write("bigint:" + number.toString());
- }
- }
- for (const type of [
- "uint8array",
- "uint8clampedarray",
- "unt8array",
- "uint16array",
- "unt16array",
- "uint32array",
- "unt32array",
- "float32array",
- "float64array"
- ]) {
- Hasher2.prototype[type] = function(arr) {
- this.write(type + ":");
- return this.array([...arr], false);
- };
- }
- function isNativeFunction(f) {
- if (typeof f !== "function") {
- return false;
- }
- return Function.prototype.toString.call(f).slice(
- -15
- /* "[native code] }".length */
- ) === "[native code] }";
- }
- return Hasher2;
-})();
-function serialize(object) {
- const hasher = new Hasher();
- hasher.dispatch(object);
- return hasher.buff;
-}
-function hash(value) {
- return digest(typeof value === "string" ? value : serialize(value)).replace(/[-_]/g, "").slice(0, 10);
-}
-
-function defaultCacheOptions() {
- return {
- name: "_",
- base: "/cache",
- swr: true,
- maxAge: 1
- };
-}
-function defineCachedFunction(fn, opts = {}) {
- opts = { ...defaultCacheOptions(), ...opts };
- const pending = {};
- const group = opts.group || "nitro/functions";
- const name = opts.name || fn.name || "_";
- const integrity = opts.integrity || hash([fn, opts]);
- const validate = opts.validate || ((entry) => entry.value !== void 0);
- async function get(key, resolver, shouldInvalidateCache, event) {
- const cacheKey = [opts.base, group, name, key + ".json"].filter(Boolean).join(":").replace(/:\/$/, ":index");
- let entry = await useStorage().getItem(cacheKey).catch((error) => {
- console.error(`[cache] Cache read error.`, error);
- useNitroApp().captureError(error, { event, tags: ["cache"] });
- }) || {};
- if (typeof entry !== "object") {
- entry = {};
- const error = new Error("Malformed data read from cache.");
- console.error("[cache]", error);
- useNitroApp().captureError(error, { event, tags: ["cache"] });
- }
- const ttl = (opts.maxAge ?? 0) * 1e3;
- if (ttl) {
- entry.expires = Date.now() + ttl;
- }
- const expired = shouldInvalidateCache || entry.integrity !== integrity || ttl && Date.now() - (entry.mtime || 0) > ttl || validate(entry) === false;
- const _resolve = async () => {
- const isPending = pending[key];
- if (!isPending) {
- if (entry.value !== void 0 && (opts.staleMaxAge || 0) >= 0 && opts.swr === false) {
- entry.value = void 0;
- entry.integrity = void 0;
- entry.mtime = void 0;
- entry.expires = void 0;
- }
- pending[key] = Promise.resolve(resolver());
- }
- try {
- entry.value = await pending[key];
- } catch (error) {
- if (!isPending) {
- delete pending[key];
- }
- throw error;
- }
- if (!isPending) {
- entry.mtime = Date.now();
- entry.integrity = integrity;
- delete pending[key];
- if (validate(entry) !== false) {
- let setOpts;
- if (opts.maxAge && !opts.swr) {
- setOpts = { ttl: opts.maxAge };
- }
- const promise = useStorage().setItem(cacheKey, entry, setOpts).catch((error) => {
- console.error(`[cache] Cache write error.`, error);
- useNitroApp().captureError(error, { event, tags: ["cache"] });
- });
- if (event?.waitUntil) {
- event.waitUntil(promise);
- }
- }
- }
- };
- const _resolvePromise = expired ? _resolve() : Promise.resolve();
- if (entry.value === void 0) {
- await _resolvePromise;
- } else if (expired && event && event.waitUntil) {
- event.waitUntil(_resolvePromise);
- }
- if (opts.swr && validate(entry) !== false) {
- _resolvePromise.catch((error) => {
- console.error(`[cache] SWR handler error.`, error);
- useNitroApp().captureError(error, { event, tags: ["cache"] });
- });
- return entry;
- }
- return _resolvePromise.then(() => entry);
- }
- return async (...args) => {
- const shouldBypassCache = await opts.shouldBypassCache?.(...args);
- if (shouldBypassCache) {
- return fn(...args);
- }
- const key = await (opts.getKey || getKey)(...args);
- const shouldInvalidateCache = await opts.shouldInvalidateCache?.(...args);
- const entry = await get(
- key,
- () => fn(...args),
- shouldInvalidateCache,
- args[0] && isEvent(args[0]) ? args[0] : void 0
- );
- let value = entry.value;
- if (opts.transform) {
- value = await opts.transform(entry, ...args) || value;
- }
- return value;
- };
-}
-function cachedFunction(fn, opts = {}) {
- return defineCachedFunction(fn, opts);
-}
-function getKey(...args) {
- return args.length > 0 ? hash(args) : "";
-}
-function escapeKey(key) {
- return String(key).replace(/\W/g, "");
-}
-function defineCachedEventHandler(handler, opts = defaultCacheOptions()) {
- const variableHeaderNames = (opts.varies || []).filter(Boolean).map((h) => h.toLowerCase()).sort();
- const _opts = {
- ...opts,
- getKey: async (event) => {
- const customKey = await opts.getKey?.(event);
- if (customKey) {
- return escapeKey(customKey);
- }
- const _path = event.node.req.originalUrl || event.node.req.url || event.path;
- let _pathname;
- try {
- _pathname = escapeKey(decodeURI(parseURL(_path).pathname)).slice(0, 16) || "index";
- } catch {
- _pathname = "-";
- }
- const _hashedPath = `${_pathname}.${hash(_path)}`;
- const _headers = variableHeaderNames.map((header) => [header, event.node.req.headers[header]]).map(([name, value]) => `${escapeKey(name)}.${hash(value)}`);
- return [_hashedPath, ..._headers].join(":");
- },
- validate: (entry) => {
- if (!entry.value) {
- return false;
- }
- if (entry.value.code >= 400) {
- return false;
- }
- if (entry.value.body === void 0) {
- return false;
- }
- if (entry.value.headers.etag === "undefined" || entry.value.headers["last-modified"] === "undefined") {
- return false;
- }
- return true;
- },
- group: opts.group || "nitro/handlers",
- integrity: opts.integrity || hash([handler, opts])
- };
- const _cachedHandler = cachedFunction(
- async (incomingEvent) => {
- const variableHeaders = {};
- for (const header of variableHeaderNames) {
- const value = incomingEvent.node.req.headers[header];
- if (value !== void 0) {
- variableHeaders[header] = value;
- }
- }
- const reqProxy = cloneWithProxy(incomingEvent.node.req, {
- headers: variableHeaders
- });
- const resHeaders = {};
- let _resSendBody;
- const resProxy = cloneWithProxy(incomingEvent.node.res, {
- statusCode: 200,
- writableEnded: false,
- writableFinished: false,
- headersSent: false,
- closed: false,
- getHeader(name) {
- return resHeaders[name];
- },
- setHeader(name, value) {
- resHeaders[name] = value;
- return this;
- },
- getHeaderNames() {
- return Object.keys(resHeaders);
- },
- hasHeader(name) {
- return name in resHeaders;
- },
- removeHeader(name) {
- delete resHeaders[name];
- },
- getHeaders() {
- return resHeaders;
- },
- end(chunk, arg2, arg3) {
- if (typeof chunk === "string") {
- _resSendBody = chunk;
- }
- if (typeof arg2 === "function") {
- arg2();
- }
- if (typeof arg3 === "function") {
- arg3();
- }
- return this;
- },
- write(chunk, arg2, arg3) {
- if (typeof chunk === "string") {
- _resSendBody = chunk;
- }
- if (typeof arg2 === "function") {
- arg2(void 0);
- }
- if (typeof arg3 === "function") {
- arg3();
- }
- return true;
- },
- writeHead(statusCode, headers2) {
- this.statusCode = statusCode;
- if (headers2) {
- if (Array.isArray(headers2) || typeof headers2 === "string") {
- throw new TypeError("Raw headers is not supported.");
- }
- for (const header in headers2) {
- const value = headers2[header];
- if (value !== void 0) {
- this.setHeader(
- header,
- value
- );
- }
- }
- }
- return this;
- }
- });
- const event = createEvent(reqProxy, resProxy);
- event.fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
- fetch: useNitroApp().localFetch
- });
- event.$fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
- fetch: globalThis.$fetch
- });
- event.waitUntil = incomingEvent.waitUntil;
- event.context = incomingEvent.context;
- event.context.cache = {
- options: _opts
- };
- const body = await handler(event) || _resSendBody;
- const headers = event.node.res.getHeaders();
- headers.etag = String(
- headers.Etag || headers.etag || `W/"${hash(body)}"`
- );
- headers["last-modified"] = String(
- headers["Last-Modified"] || headers["last-modified"] || (/* @__PURE__ */ new Date()).toUTCString()
- );
- const cacheControl = [];
- if (opts.swr) {
- if (opts.maxAge) {
- cacheControl.push(`s-maxage=${opts.maxAge}`);
- }
- if (opts.staleMaxAge) {
- cacheControl.push(`stale-while-revalidate=${opts.staleMaxAge}`);
- } else {
- cacheControl.push("stale-while-revalidate");
- }
- } else if (opts.maxAge) {
- cacheControl.push(`max-age=${opts.maxAge}`);
- }
- if (cacheControl.length > 0) {
- headers["cache-control"] = cacheControl.join(", ");
- }
- const cacheEntry = {
- code: event.node.res.statusCode,
- headers,
- body
- };
- return cacheEntry;
- },
- _opts
- );
- return defineEventHandler(async (event) => {
- if (opts.headersOnly) {
- if (handleCacheHeaders(event, { maxAge: opts.maxAge })) {
- return;
- }
- return handler(event);
- }
- const response = await _cachedHandler(
- event
- );
- if (event.node.res.headersSent || event.node.res.writableEnded) {
- return response.body;
- }
- if (handleCacheHeaders(event, {
- modifiedTime: new Date(response.headers["last-modified"]),
- etag: response.headers.etag,
- maxAge: opts.maxAge
- })) {
- return;
- }
- event.node.res.statusCode = response.code;
- for (const name in response.headers) {
- const value = response.headers[name];
- if (name === "set-cookie") {
- event.node.res.appendHeader(
- name,
- splitCookiesString(value)
- );
- } else {
- if (value !== void 0) {
- event.node.res.setHeader(name, value);
- }
- }
- }
- return response.body;
- });
-}
-function cloneWithProxy(obj, overrides) {
- return new Proxy(obj, {
- get(target, property, receiver) {
- if (property in overrides) {
- return overrides[property];
- }
- return Reflect.get(target, property, receiver);
- },
- set(target, property, value, receiver) {
- if (property in overrides) {
- overrides[property] = value;
- return true;
- }
- return Reflect.set(target, property, value, receiver);
- }
- });
-}
-const cachedEventHandler = defineCachedEventHandler;
-
-const inlineAppConfig = {
- "nuxt": {}
-};
-
-
-
-const appConfig = defuFn(inlineAppConfig);
-
-function getEnv(key, opts) {
- const envKey = snakeCase(key).toUpperCase();
- return destr(
- process.env[opts.prefix + envKey] ?? process.env[opts.altPrefix + envKey]
- );
-}
-function _isObject(input) {
- return typeof input === "object" && !Array.isArray(input);
-}
-function applyEnv(obj, opts, parentKey = "") {
- for (const key in obj) {
- const subKey = parentKey ? `${parentKey}_${key}` : key;
- const envValue = getEnv(subKey, opts);
- if (_isObject(obj[key])) {
- if (_isObject(envValue)) {
- obj[key] = { ...obj[key], ...envValue };
- applyEnv(obj[key], opts, subKey);
- } else if (envValue === void 0) {
- applyEnv(obj[key], opts, subKey);
- } else {
- obj[key] = envValue ?? obj[key];
- }
- } else {
- obj[key] = envValue ?? obj[key];
- }
- if (opts.envExpansion && typeof obj[key] === "string") {
- obj[key] = _expandFromEnv(obj[key]);
- }
- }
- return obj;
-}
-const envExpandRx = /\{\{([^{}]*)\}\}/g;
-function _expandFromEnv(value) {
- return value.replace(envExpandRx, (match, key) => {
- return process.env[key] || match;
- });
-}
-
-const _inlineRuntimeConfig = {
- "app": {
- "baseURL": "/",
- "buildId": "dev",
- "buildAssetsDir": "/_nuxt/",
- "cdnURL": ""
- },
- "nitro": {
- "envPrefix": "NUXT_",
- "routeRules": {
- "/__nuxt_error": {
- "cache": false
- },
- "/_nuxt/builds/meta/**": {
- "headers": {
- "cache-control": "public, max-age=31536000, immutable"
- }
- },
- "/_nuxt/builds/**": {
- "headers": {
- "cache-control": "public, max-age=1, immutable"
- }
- }
- }
- },
- "public": {},
- "vatstackApiKey": ""
-};
-const envOptions = {
- prefix: "NITRO_",
- altPrefix: _inlineRuntimeConfig.nitro.envPrefix ?? process.env.NITRO_ENV_PREFIX ?? "_",
- envExpansion: _inlineRuntimeConfig.nitro.envExpansion ?? process.env.NITRO_ENV_EXPANSION ?? false
-};
-const _sharedRuntimeConfig = _deepFreeze(
- applyEnv(klona(_inlineRuntimeConfig), envOptions)
-);
-function useRuntimeConfig(event) {
- if (!event) {
- return _sharedRuntimeConfig;
- }
- if (event.context.nitro.runtimeConfig) {
- return event.context.nitro.runtimeConfig;
- }
- const runtimeConfig = klona(_inlineRuntimeConfig);
- applyEnv(runtimeConfig, envOptions);
- event.context.nitro.runtimeConfig = runtimeConfig;
- return runtimeConfig;
-}
-_deepFreeze(klona(appConfig));
-function _deepFreeze(object) {
- const propNames = Object.getOwnPropertyNames(object);
- for (const name of propNames) {
- const value = object[name];
- if (value && typeof value === "object") {
- _deepFreeze(value);
- }
- }
- return Object.freeze(object);
-}
-new Proxy(/* @__PURE__ */ Object.create(null), {
- get: (_, prop) => {
- console.warn(
- "Please use `useRuntimeConfig()` instead of accessing config directly."
- );
- const runtimeConfig = useRuntimeConfig();
- if (prop in runtimeConfig) {
- return runtimeConfig[prop];
- }
- return void 0;
- }
-});
-
-getContext("nitro-app", {
- asyncContext: false,
- AsyncLocalStorage: void 0
-});
-
-const config = useRuntimeConfig();
-const _routeRulesMatcher = toRouteMatcher(
- createRouter({ routes: config.nitro.routeRules })
-);
-function createRouteRulesHandler(ctx) {
- return eventHandler((event) => {
- const routeRules = getRouteRules(event);
- if (routeRules.headers) {
- setHeaders(event, routeRules.headers);
- }
- if (routeRules.redirect) {
- let target = routeRules.redirect.to;
- if (target.endsWith("/**")) {
- let targetPath = event.path;
- const strpBase = routeRules.redirect._redirectStripBase;
- if (strpBase) {
- targetPath = withoutBase(targetPath, strpBase);
- }
- target = joinURL(target.slice(0, -3), targetPath);
- } else if (event.path.includes("?")) {
- const query = getQuery(event.path);
- target = withQuery(target, query);
- }
- return sendRedirect(event, target, routeRules.redirect.statusCode);
- }
- if (routeRules.proxy) {
- let target = routeRules.proxy.to;
- if (target.endsWith("/**")) {
- let targetPath = event.path;
- const strpBase = routeRules.proxy._proxyStripBase;
- if (strpBase) {
- targetPath = withoutBase(targetPath, strpBase);
- }
- target = joinURL(target.slice(0, -3), targetPath);
- } else if (event.path.includes("?")) {
- const query = getQuery(event.path);
- target = withQuery(target, query);
- }
- return proxyRequest(event, target, {
- fetch: ctx.localFetch,
- ...routeRules.proxy
- });
- }
- });
-}
-function getRouteRules(event) {
- event.context._nitro = event.context._nitro || {};
- if (!event.context._nitro.routeRules) {
- event.context._nitro.routeRules = getRouteRulesForPath(
- withoutBase(event.path.split("?")[0], useRuntimeConfig().app.baseURL)
- );
- }
- return event.context._nitro.routeRules;
-}
-function getRouteRulesForPath(path) {
- return defu({}, ..._routeRulesMatcher.matchAll(path).reverse());
-}
-
-function _captureError(error, type) {
- console.error(`[${type}]`, error);
- useNitroApp().captureError(error, { tags: [type] });
-}
-function trapUnhandledNodeErrors() {
- process.on(
- "unhandledRejection",
- (error) => _captureError(error, "unhandledRejection")
- );
- process.on(
- "uncaughtException",
- (error) => _captureError(error, "uncaughtException")
- );
-}
-function joinHeaders(value) {
- return Array.isArray(value) ? value.join(", ") : String(value);
-}
-function normalizeFetchResponse(response) {
- if (!response.headers.has("set-cookie")) {
- return response;
- }
- return new Response(response.body, {
- status: response.status,
- statusText: response.statusText,
- headers: normalizeCookieHeaders(response.headers)
- });
-}
-function normalizeCookieHeader(header = "") {
- return splitCookiesString(joinHeaders(header));
-}
-function normalizeCookieHeaders(headers) {
- const outgoingHeaders = new Headers();
- for (const [name, header] of headers) {
- if (name === "set-cookie") {
- for (const cookie of normalizeCookieHeader(header)) {
- outgoingHeaders.append("set-cookie", cookie);
- }
- } else {
- outgoingHeaders.set(name, joinHeaders(header));
- }
- }
- return outgoingHeaders;
-}
-
-/**
-* Nitro internal functions extracted from https://github.com/nitrojs/nitro/blob/v2/src/runtime/internal/utils.ts
-*/
-function isJsonRequest(event) {
- // If the client specifically requests HTML, then avoid classifying as JSON.
- if (hasReqHeader(event, "accept", "text/html")) {
- return false;
- }
- return hasReqHeader(event, "accept", "application/json") || hasReqHeader(event, "user-agent", "curl/") || hasReqHeader(event, "user-agent", "httpie/") || hasReqHeader(event, "sec-fetch-mode", "cors") || event.path.startsWith("/api/") || event.path.endsWith(".json");
-}
-function hasReqHeader(event, name, includes) {
- const value = getRequestHeader(event, name);
- return value && typeof value === "string" && value.toLowerCase().includes(includes);
-}
-
-const iframeStorageBridge = (nonce) => `
-(function () {
- const NONCE = ${JSON.stringify(nonce)};
- const memoryStore = Object.create(null);
-
- const post = (type, payload) => {
- window.parent.postMessage({ type, nonce: NONCE, ...payload }, '*');
- };
-
- const isValid = (data) => data && data.nonce === NONCE;
-
- const mockStorage = {
- getItem(key) {
- return Object.hasOwn(memoryStore, key)
- ? memoryStore[key]
- : null;
- },
- setItem(key, value) {
- const v = String(value);
- memoryStore[key] = v;
- post('storage-set', { key, value: v });
- },
- removeItem(key) {
- delete memoryStore[key];
- post('storage-remove', { key });
- },
- clear() {
- for (const key of Object.keys(memoryStore))
- delete memoryStore[key];
- post('storage-clear', {});
- },
- key(index) {
- const keys = Object.keys(memoryStore);
- return keys[index] ?? null;
- },
- get length() {
- return Object.keys(memoryStore).length;
- }
- };
-
- const defineLocalStorage = () => {
- try {
- Object.defineProperty(window, 'localStorage', {
- value: mockStorage,
- writable: false,
- configurable: true
- });
- } catch {
- window.localStorage = mockStorage;
- }
- };
-
- defineLocalStorage();
-
- window.addEventListener('message', (event) => {
- const data = event.data;
- if (!isValid(data) || data.type !== 'storage-sync-data') return;
-
- const incoming = data.data || {};
- for (const key of Object.keys(incoming))
- memoryStore[key] = incoming[key];
-
- if (typeof window.initTheme === 'function')
- window.initTheme();
- window.dispatchEvent(new Event('storage-ready'));
- });
-
- // Clipboard API is unavailable in data: URL iframe, so we use postMessage
- document.addEventListener('DOMContentLoaded', function() {
- window.copyErrorMessage = function(button) {
- post('clipboard-copy', { text: button.dataset.errorText });
- button.classList.add('copied');
- setTimeout(function() { button.classList.remove('copied'); }, 2000);
- };
- });
-
- post('storage-sync-request', {});
-})();
-`;
-const parentStorageBridge = (nonce) => `
-(function () {
- const host = document.querySelector('nuxt-error-overlay');
- if (!host) return;
-
- const NONCE = ${JSON.stringify(nonce)};
- const isValid = (data) => data && data.nonce === NONCE;
-
- // Handle clipboard copy from iframe
- window.addEventListener('message', function(e) {
- if (isValid(e) && e.data.type === 'clipboard-copy') {
- navigator.clipboard.writeText(e.data.text).catch(function() {});
- }
- });
-
- const collectLocalStorage = () => {
- const all = {};
- for (let i = 0; i < localStorage.length; i++) {
- const k = localStorage.key(i);
- if (k != null) all[k] = localStorage.getItem(k);
- }
- return all;
- };
-
- const attachWhenReady = () => {
- const root = host.shadowRoot;
- if (!root)
- return false;
- const iframe = root.getElementById('frame');
- if (!iframe || !iframe.contentWindow)
- return false;
-
- const handlers = {
- 'storage-set': (d) => localStorage.setItem(d.key, d.value),
- 'storage-remove': (d) => localStorage.removeItem(d.key),
- 'storage-clear': () => localStorage.clear(),
- 'storage-sync-request': () => {
- iframe.contentWindow.postMessage({
- type: 'storage-sync-data',
- data: collectLocalStorage(),
- nonce: NONCE
- }, '*');
- }
- };
-
- window.addEventListener('message', (event) => {
- const data = event.data;
- if (!isValid(data)) return;
- const fn = handlers[data.type];
- if (fn) fn(data);
- });
-
- return true;
- };
-
- if (attachWhenReady())
- return;
-
- const obs = new MutationObserver(() => {
- if (attachWhenReady())
- obs.disconnect();
- });
-
- obs.observe(host, { childList: true, subtree: true });
-})();
-`;
-const errorCSS = `
-:host {
- --preview-width: 240px;
- --preview-height: 180px;
- --base-width: 1200px;
- --base-height: 900px;
- --z-base: 999999998;
- --error-pip-left: auto;
- --error-pip-top: auto;
- --error-pip-right: 5px;
- --error-pip-bottom: 5px;
- --error-pip-origin: bottom right;
- --app-preview-left: auto;
- --app-preview-top: auto;
- --app-preview-right: 5px;
- --app-preview-bottom: 5px;
- all: initial;
- display: contents;
-}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
- border-width: 0;
-}
-#frame {
- position: fixed;
- left: 0;
- top: 0;
- width: 100vw;
- height: 100vh;
- border: none;
- z-index: var(--z-base);
-}
-#frame[inert] {
- left: var(--error-pip-left);
- top: var(--error-pip-top);
- right: var(--error-pip-right);
- bottom: var(--error-pip-bottom);
- width: var(--base-width);
- height: var(--base-height);
- transform: scale(calc(240 / 1200));
- transform-origin: var(--error-pip-origin);
- overflow: hidden;
- border-radius: calc(1200 * 8px / 240);
-}
-#preview {
- position: fixed;
- left: var(--app-preview-left);
- top: var(--app-preview-top);
- right: var(--app-preview-right);
- bottom: var(--app-preview-bottom);
- width: var(--preview-width);
- height: var(--preview-height);
- overflow: hidden;
- border-radius: 6px;
- pointer-events: none;
- z-index: var(--z-base);
- background: white;
- display: none;
-}
-#preview iframe {
- transform-origin: var(--error-pip-origin);
-}
-#frame:not([inert]) + #preview {
- display: block;
-}
-#toggle {
- position: fixed;
- left: var(--app-preview-left);
- top: var(--app-preview-top);
- right: calc(var(--app-preview-right) - 3px);
- bottom: calc(var(--app-preview-bottom) - 3px);
- width: var(--preview-width);
- height: var(--preview-height);
- background: none;
- border: 3px solid #00DC82;
- border-radius: 8px;
- cursor: pointer;
- opacity: 0.8;
- transition: opacity 0.2s, box-shadow 0.2s;
- z-index: calc(var(--z-base) + 1);
- display: flex;
- align-items: center;
- justify-content: center;
-}
-#toggle:hover,
-#toggle:focus {
- opacity: 1;
- box-shadow: 0 0 20px rgba(0, 220, 130, 0.6);
-}
-#toggle:focus-visible {
- outline: 3px solid #00DC82;
- outline-offset: 0;
- box-shadow: 0 0 24px rgba(0, 220, 130, 0.8);
-}
-#frame[inert] ~ #toggle {
- left: var(--error-pip-left);
- top: var(--error-pip-top);
- right: calc(var(--error-pip-right) - 3px);
- bottom: calc(var(--error-pip-bottom) - 3px);
- cursor: grab;
-}
-:host(.dragging) #frame[inert] ~ #toggle {
- cursor: grabbing;
-}
-#frame:not([inert]) ~ #toggle,
-#frame:not([inert]) + #preview {
- cursor: grab;
-}
-:host(.dragging-preview) #frame:not([inert]) ~ #toggle,
-:host(.dragging-preview) #frame:not([inert]) + #preview {
- cursor: grabbing;
-}
-
-#pip-close {
- position: absolute;
- top: 6px;
- right: 6px;
- width: 24px;
- height: 24px;
- border-radius: 50%;
- border: none;
- background: rgba(0, 0, 0, 0.75);
- color: #fff;
- font-size: 16px;
- line-height: 1;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
- pointer-events: auto;
-}
-#pip-close:focus-visible {
- outline: 2px solid #00DC82;
- outline-offset: 2px;
-}
-
-#pip-restore {
- position: fixed;
- right: 16px;
- bottom: 16px;
- padding: 8px 14px;
- border-radius: 999px;
- border: 2px solid #00DC82;
- background: #111;
- color: #fff;
- font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
- font-size: 14px;
- display: inline-flex;
- align-items: center;
- gap: 6px;
- z-index: calc(var(--z-base) + 2);
- cursor: grab;
-}
-#pip-restore:focus-visible {
- outline: 2px solid #00DC82;
- outline-offset: 2px;
-}
-:host(.dragging-restore) #pip-restore {
- cursor: grabbing;
-}
-
-#frame[hidden],
-#toggle[hidden],
-#preview[hidden],
-#pip-restore[hidden],
-#pip-close[hidden] {
- display: none !important;
-}
-
-@media (prefers-reduced-motion: reduce) {
- #toggle {
- transition: none;
- }
-}
-`;
-function webComponentScript(base64HTML, startMinimized) {
- return `
-(function () {
- try {
- // =========================
- // Host + Shadow
- // =========================
- const host = document.querySelector('nuxt-error-overlay');
- if (!host)
- return;
- const shadow = host.attachShadow({ mode: 'open' });
-
- // =========================
- // DOM helpers
- // =========================
- const el = (tag) => document.createElement(tag);
- const on = (node, type, fn, opts) => node.addEventListener(type, fn, opts);
- const hide = (node, v) => node.toggleAttribute('hidden', !!v);
- const setVar = (name, value) => host.style.setProperty(name, value);
- const unsetVar = (name) => host.style.removeProperty(name);
-
- // =========================
- // Create DOM
- // =========================
- const style = el('style');
- style.textContent = ${JSON.stringify(errorCSS)};
-
- const iframe = el('iframe');
- iframe.id = 'frame';
- iframe.src = 'data:text/html;base64,${base64HTML}';
- iframe.title = 'Detailed error stack trace';
- iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
-
- const preview = el('div');
- preview.id = 'preview';
-
- const toggle = el('div');
- toggle.id = 'toggle';
- toggle.setAttribute('aria-expanded', 'true');
- toggle.setAttribute('role', 'button');
- toggle.setAttribute('tabindex', '0');
- toggle.innerHTML = 'Toggle detailed error view';
-
- const liveRegion = el('div');
- liveRegion.setAttribute('role', 'status');
- liveRegion.setAttribute('aria-live', 'polite');
- liveRegion.className = 'sr-only';
-
- const pipCloseButton = el('button');
- pipCloseButton.id = 'pip-close';
- pipCloseButton.setAttribute('type', 'button');
- pipCloseButton.setAttribute('aria-label', 'Hide error preview overlay');
- pipCloseButton.innerHTML = '×';
- pipCloseButton.hidden = true;
- toggle.appendChild(pipCloseButton);
-
- const pipRestoreButton = el('button');
- pipRestoreButton.id = 'pip-restore';
- pipRestoreButton.setAttribute('type', 'button');
- pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
- pipRestoreButton.innerHTML = '⟲Show error overlay';
- pipRestoreButton.hidden = true;
-
- // Order matters: #frame + #preview adjacency
- shadow.appendChild(style);
- shadow.appendChild(liveRegion);
- shadow.appendChild(iframe);
- shadow.appendChild(preview);
- shadow.appendChild(toggle);
- shadow.appendChild(pipRestoreButton);
-
- // =========================
- // Constants / keys
- // =========================
- const POS_KEYS = {
- position: 'nuxt-error-overlay:position',
- hiddenPretty: 'nuxt-error-overlay:error-pip:hidden',
- hiddenPreview: 'nuxt-error-overlay:app-preview:hidden'
- };
-
- const CSS_VARS = {
- pip: {
- left: '--error-pip-left',
- top: '--error-pip-top',
- right: '--error-pip-right',
- bottom: '--error-pip-bottom'
- },
- preview: {
- left: '--app-preview-left',
- top: '--app-preview-top',
- right: '--app-preview-right',
- bottom: '--app-preview-bottom'
- }
- };
-
- const MIN_GAP = 5;
- const DRAG_THRESHOLD = 2;
-
- // =========================
- // Local storage safe access + state
- // =========================
- let storageReady = true;
- let isPrettyHidden = false;
- let isPreviewHidden = false;
-
- const safeGet = (k) => {
- try {
- return localStorage.getItem(k);
- } catch {
- return null;
- }
- };
-
- const safeSet = (k, v) => {
- if (!storageReady)
- return;
- try {
- localStorage.setItem(k, v);
- } catch {}
- };
-
- // =========================
- // Sizing helpers
- // =========================
- const vvSize = () => {
- const v = window.visualViewport;
- return v ? { w: v.width, h: v.height } : { w: window.innerWidth, h: window.innerHeight };
- };
-
- const previewSize = () => {
- const styles = getComputedStyle(host);
- const w = parseFloat(styles.getPropertyValue('--preview-width')) || 240;
- const h = parseFloat(styles.getPropertyValue('--preview-height')) || 180;
- return { w, h };
- };
-
- const sizeForTarget = (target) => {
- if (!target)
- return previewSize();
- const rect = target.getBoundingClientRect();
- if (rect.width && rect.height)
- return { w: rect.width, h: rect.height };
- return previewSize();
- };
-
- // =========================
- // Dock model + offset/alignment calculations
- // =========================
- const dock = { edge: null, offset: null, align: null, gap: null };
-
- const maxOffsetFor = (edge, size) => {
- const vv = vvSize();
- if (edge === 'left' || edge === 'right')
- return Math.max(MIN_GAP, vv.h - size.h - MIN_GAP);
- return Math.max(MIN_GAP, vv.w - size.w - MIN_GAP);
- };
-
- const clampOffset = (edge, value, size) => {
- const max = maxOffsetFor(edge, size);
- return Math.min(Math.max(value, MIN_GAP), max);
- };
-
- const updateDockAlignment = (size) => {
- if (!dock.edge || dock.offset == null)
- return;
- const max = maxOffsetFor(dock.edge, size);
- if (dock.offset <= max / 2) {
- dock.align = 'start';
- dock.gap = dock.offset;
- } else {
- dock.align = 'end';
- dock.gap = Math.max(0, max - dock.offset);
- }
- };
-
- const appliedOffsetFor = (size) => {
- if (!dock.edge || dock.offset == null)
- return null;
- const max = maxOffsetFor(dock.edge, size);
-
- if (dock.align === 'end' && typeof dock.gap === 'number') {
- return clampOffset(dock.edge, max - dock.gap, size);
- }
- if (dock.align === 'start' && typeof dock.gap === 'number') {
- return clampOffset(dock.edge, dock.gap, size);
- }
- return clampOffset(dock.edge, dock.offset, size);
- };
-
- const nearestEdgeAt = (x, y) => {
- const { w, h } = vvSize();
- const d = { left: x, right: w - x, top: y, bottom: h - y };
- return Object.keys(d).reduce((a, b) => (d[a] < d[b] ? a : b));
- };
-
- const cornerDefaultDock = () => {
- const vv = vvSize();
- const size = previewSize();
- const offset = Math.max(MIN_GAP, vv.w - size.w - MIN_GAP);
- return { edge: 'bottom', offset };
- };
-
- const currentTransformOrigin = () => {
- if (!dock.edge) return null;
- if (dock.edge === 'left' || dock.edge === 'top')
- return 'top left';
- if (dock.edge === 'right')
- return 'top right';
- return 'bottom left';
- };
-
- // =========================
- // Persist / load dock
- // =========================
- const loadDock = () => {
- const raw = safeGet(POS_KEYS.position);
- if (!raw)
- return;
- try {
- const parsed = JSON.parse(raw);
- const { edge, offset, align, gap } = parsed || {};
- if (!['left', 'right', 'top', 'bottom'].includes(edge))
- return;
- if (typeof offset !== 'number')
- return;
-
- dock.edge = edge;
- dock.offset = clampOffset(edge, offset, previewSize());
- dock.align = align === 'start' || align === 'end' ? align : null;
- dock.gap = typeof gap === 'number' ? gap : null;
-
- if (!dock.align || dock.gap == null)
- updateDockAlignment(previewSize());
- } catch {}
- };
-
- const persistDock = () => {
- if (!dock.edge || dock.offset == null)
- return;
- safeSet(POS_KEYS.position, JSON.stringify({
- edge: dock.edge,
- offset: dock.offset,
- align: dock.align,
- gap: dock.gap
- }));
- };
-
- // =========================
- // Apply dock
- // =========================
- const dockToVars = (vars) => ({
- set: (side, v) => host.style.setProperty(vars[side], v),
- clear: (side) => host.style.removeProperty(vars[side])
- });
-
- const dockToEl = (node) => ({
- set: (side, v) => { node.style[side] = v; },
- clear: (side) => { node.style[side] = ''; }
- });
-
- const applyDock = (target, size, opts) => {
- if (!dock.edge || dock.offset == null) {
- target.clear('left');
- target.clear('top');
- target.clear('right');
- target.clear('bottom');
- return;
- }
-
- target.set('left', 'auto');
- target.set('top', 'auto');
- target.set('right', 'auto');
- target.set('bottom', 'auto');
-
- const applied = appliedOffsetFor(size);
-
- if (dock.edge === 'left') {
- target.set('left', MIN_GAP + 'px');
- target.set('top', applied + 'px');
- } else if (dock.edge === 'right') {
- target.set('right', MIN_GAP + 'px');
- target.set('top', applied + 'px');
- } else if (dock.edge === 'top') {
- target.set('top', MIN_GAP + 'px');
- target.set('left', applied + 'px');
- } else {
- target.set('bottom', MIN_GAP + 'px');
- target.set('left', applied + 'px');
- }
-
- if (!opts || opts.persist !== false)
- persistDock();
- };
-
- const applyDockAll = (opts) => {
- applyDock(dockToVars(CSS_VARS.pip), previewSize(), opts);
- applyDock(dockToVars(CSS_VARS.preview), previewSize(), opts);
- applyDock(dockToEl(pipRestoreButton), sizeForTarget(pipRestoreButton), opts);
- };
-
- const repaintToDock = () => {
- if (!dock.edge || dock.offset == null)
- return;
- const origin = currentTransformOrigin();
- if (origin)
- setVar('--error-pip-origin', origin);
- else
- unsetVar('--error-pip-origin');
- applyDockAll({ persist: false });
- };
-
- // =========================
- // Hidden state + UI
- // =========================
- const loadHidden = () => {
- const rawPretty = safeGet(POS_KEYS.hiddenPretty);
- if (rawPretty != null)
- isPrettyHidden = rawPretty === '1' || rawPretty === 'true';
- const rawPreview = safeGet(POS_KEYS.hiddenPreview);
- if (rawPreview != null)
- isPreviewHidden = rawPreview === '1' || rawPreview === 'true';
- };
-
- const setPrettyHidden = (v) => {
- isPrettyHidden = !!v;
- safeSet(POS_KEYS.hiddenPretty, isPrettyHidden ? '1' : '0');
- updateUI();
- };
-
- const setPreviewHidden = (v) => {
- isPreviewHidden = !!v;
- safeSet(POS_KEYS.hiddenPreview, isPreviewHidden ? '1' : '0');
- updateUI();
- };
-
- const isMinimized = () => iframe.hasAttribute('inert');
-
- const setMinimized = (v) => {
- if (v) {
- iframe.setAttribute('inert', '');
- toggle.setAttribute('aria-expanded', 'false');
- } else {
- iframe.removeAttribute('inert');
- toggle.setAttribute('aria-expanded', 'true');
- }
- };
-
- const setRestoreLabel = (kind) => {
- if (kind === 'pretty') {
- pipRestoreButton.innerHTML = '⟲Show error overlay';
- pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
- } else {
- pipRestoreButton.innerHTML = '⟲Show error page';
- pipRestoreButton.setAttribute('aria-label', 'Show error page');
- }
- };
-
- const updateUI = () => {
- const minimized = isMinimized();
- const showPiP = minimized && !isPrettyHidden;
- const showPreview = !minimized && !isPreviewHidden;
- const pipHiddenByUser = minimized && isPrettyHidden;
- const previewHiddenByUser = !minimized && isPreviewHidden;
- const showToggle = minimized ? showPiP : showPreview;
- const showRestore = pipHiddenByUser || previewHiddenByUser;
-
- hide(iframe, pipHiddenByUser);
- hide(preview, !showPreview);
- hide(toggle, !showToggle);
- hide(pipCloseButton, !showToggle);
- hide(pipRestoreButton, !showRestore);
-
- pipCloseButton.setAttribute('aria-label', minimized ? 'Hide error overlay' : 'Hide error page preview');
-
- if (pipHiddenByUser)
- setRestoreLabel('pretty');
- else if (previewHiddenByUser)
- setRestoreLabel('preview');
-
- host.classList.toggle('pip-hidden', isPrettyHidden);
- host.classList.toggle('preview-hidden', isPreviewHidden);
- };
-
- // =========================
- // Preview snapshot
- // =========================
- const updatePreview = () => {
- try {
- let previewIframe = preview.querySelector('iframe');
- if (!previewIframe) {
- previewIframe = el('iframe');
- previewIframe.style.cssText = 'width: 1200px; height: 900px; transform: scale(0.2); transform-origin: top left; border: none;';
- previewIframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
- preview.appendChild(previewIframe);
- }
-
- const doctype = document.doctype ? '' : '';
- const cleanedHTML = document.documentElement.outerHTML
- .replace(/]*>.*?<\\/nuxt-error-overlay>/gs, '')
- .replace(/