From 2e02d6d763d2ff058cd5af070c32ae555935df57 Mon Sep 17 00:00:00 2001 From: Bennet Gallein Date: Fri, 13 Feb 2026 23:49:12 +0100 Subject: [PATCH] fix: a --- .gitignore | 144 + .nuxt/dev/index.mjs | 3497 ----------------- .nuxt/dev/index.mjs.map | 1 - .nuxt/dist/server/client.manifest.mjs | 4 - .nuxt/dist/server/client.precomputed.mjs | 1 - .nuxt/dist/server/server.mjs | 1 - .nuxt/imports.d.ts | 3 +- .nuxt/manifest/latest.json | 1 - .../4d48d991-b9bc-47d1-b3d9-7f74721487c8.json | 1 - .nuxt/manifest/meta/dev.json | 1 - .nuxt/nitro.json | 17 - .nuxt/nuxt.d.ts | 2 +- .nuxt/nuxt.node.d.ts | 2 +- .nuxt/tailwind/postcss.mjs | 2 +- .nuxt/tsconfig.app.json | 4 +- .nuxt/tsconfig.json | 2 +- .nuxt/tsconfig.shared.json | 2 +- .nuxt/types/build.d.ts | 2 - .nuxt/types/imports.d.ts | 2 - .nuxt/types/plugins.d.ts | 11 +- Dockerfile | 2 + app/assets/css/main.css | 2 +- app/components/FooterSection.vue | 12 +- node_modules/.package-lock.json | 100 +- node_modules/commander/Readme.md | 75 +- node_modules/commander/esm.mjs | 2 +- node_modules/commander/index.js | 10 +- node_modules/commander/lib/argument.js | 16 +- node_modules/commander/lib/command.js | 1191 ++++-- node_modules/commander/lib/error.js | 4 - node_modules/commander/lib/help.js | 447 ++- node_modules/commander/lib/option.js | 84 +- node_modules/commander/lib/suggestSimilar.js | 9 +- node_modules/commander/package.json | 48 +- node_modules/commander/typings/index.d.ts | 273 +- package-lock.json | 19 +- 36 files changed, 1816 insertions(+), 4178 deletions(-) create mode 100644 .gitignore delete mode 100644 .nuxt/dev/index.mjs delete mode 100644 .nuxt/dev/index.mjs.map delete mode 100644 .nuxt/dist/server/client.manifest.mjs delete mode 100644 .nuxt/dist/server/client.precomputed.mjs delete mode 100644 .nuxt/dist/server/server.mjs delete mode 100644 .nuxt/manifest/latest.json delete mode 100644 .nuxt/manifest/meta/4d48d991-b9bc-47d1-b3d9-7f74721487c8.json delete mode 100644 .nuxt/manifest/meta/dev.json delete mode 100644 .nuxt/nitro.json 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(/]*>.*?<\\/script>/gs, ''); - - const iframeDoc = previewIframe.contentDocument || previewIframe.contentWindow.document; - iframeDoc.open(); - iframeDoc.write(doctype + cleanedHTML); - iframeDoc.close(); - } catch (err) { - console.error('Failed to update preview:', err); - } - }; - - // ========================= - // View toggling - // ========================= - const toggleView = () => { - if (isMinimized()) { - updatePreview(); - setMinimized(false); - liveRegion.textContent = 'Showing detailed error view'; - setTimeout(() => { - try { - iframe.contentWindow.focus(); - } catch {} - }, 100); - } else { - setMinimized(true); - liveRegion.textContent = 'Showing error page'; - repaintToDock(); - void iframe.offsetWidth; - } - updateUI(); - }; - - // ========================= - // Dragging (unified, rAF throttled) - // ========================= - let drag = null; - let rafId = null; - let suppressToggleClick = false; - let suppressRestoreClick = false; - - const beginDrag = (e) => { - if (drag) - return; - - if (!dock.edge || dock.offset == null) { - const def = cornerDefaultDock(); - dock.edge = def.edge; - dock.offset = def.offset; - updateDockAlignment(previewSize()); - } - - const isRestoreTarget = e.currentTarget === pipRestoreButton; - - drag = { - kind: isRestoreTarget ? 'restore' : (isMinimized() ? 'pip' : 'preview'), - pointerId: e.pointerId, - startX: e.clientX, - startY: e.clientY, - lastX: e.clientX, - lastY: e.clientY, - moved: false, - target: e.currentTarget - }; - - drag.target.setPointerCapture(e.pointerId); - - if (drag.kind === 'restore') - host.classList.add('dragging-restore'); - else - host.classList.add(drag.kind === 'pip' ? 'dragging' : 'dragging-preview'); - - e.preventDefault(); - }; - - const moveDrag = (e) => { - if (!drag || drag.pointerId !== e.pointerId) - return; - - drag.lastX = e.clientX; - drag.lastY = e.clientY; - - const dx = drag.lastX - drag.startX; - const dy = drag.lastY - drag.startY; - - if (!drag.moved && (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD)) { - drag.moved = true; - } - - if (!drag.moved) - return; - if (rafId) - return; - - rafId = requestAnimationFrame(() => { - rafId = null; - - const edge = nearestEdgeAt(drag.lastX, drag.lastY); - const size = sizeForTarget(drag.target); - - let offset; - if (edge === 'left' || edge === 'right') { - const top = drag.lastY - (size.h / 2); - offset = clampOffset(edge, Math.round(top), size); - } else { - const left = drag.lastX - (size.w / 2); - offset = clampOffset(edge, Math.round(left), size); - } - - dock.edge = edge; - dock.offset = offset; - updateDockAlignment(size); - - const origin = currentTransformOrigin(); - setVar('--error-pip-origin', origin || 'bottom right'); - - applyDockAll({ persist: false }); - }); - }; - - const endDrag = (e) => { - if (!drag || drag.pointerId !== e.pointerId) - return; - - const endedKind = drag.kind; - drag.target.releasePointerCapture(e.pointerId); - - if (endedKind === 'restore') - host.classList.remove('dragging-restore'); - else - host.classList.remove(endedKind === 'pip' ? 'dragging' : 'dragging-preview'); - - const didMove = drag.moved; - drag = null; - - if (didMove) { - persistDock(); - if (endedKind === 'restore') - suppressRestoreClick = true; - else - suppressToggleClick = true; - e.preventDefault(); - e.stopPropagation(); - } - }; - - const bindDragTarget = (node) => { - on(node, 'pointerdown', beginDrag); - on(node, 'pointermove', moveDrag); - on(node, 'pointerup', endDrag); - on(node, 'pointercancel', endDrag); - }; - - bindDragTarget(toggle); - bindDragTarget(pipRestoreButton); - - // ========================= - // Events (toggle / close / restore) - // ========================= - on(toggle, 'click', (e) => { - if (suppressToggleClick) { - e.preventDefault(); - suppressToggleClick = false; - return; - } - toggleView(); - }); - - on(toggle, 'keydown', (e) => { - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - toggleView(); - } - }); - - on(pipCloseButton, 'click', (e) => { - e.preventDefault(); - e.stopPropagation(); - if (isMinimized()) - setPrettyHidden(true); - else - setPreviewHidden(true); - }); - - on(pipCloseButton, 'pointerdown', (e) => { - e.stopPropagation(); - }); - - on(pipRestoreButton, 'click', (e) => { - if (suppressRestoreClick) { - e.preventDefault(); - suppressRestoreClick = false; - return; - } - e.preventDefault(); - e.stopPropagation(); - if (isMinimized()) - setPrettyHidden(false); - else - setPreviewHidden(false); - }); - - // ========================= - // Lifecycle: load / sync / repaint - // ========================= - const loadState = () => { - loadDock(); - loadHidden(); - - if (isPrettyHidden && !isMinimized()) - setMinimized(true); - - updateUI(); - repaintToDock(); - }; - - loadState(); - - on(window, 'storage-ready', () => { - storageReady = true; - loadState(); - }); - - const onViewportChange = () => repaintToDock(); - - on(window, 'resize', onViewportChange); - - if (window.visualViewport) { - on(window.visualViewport, 'resize', onViewportChange); - on(window.visualViewport, 'scroll', onViewportChange); - } - - // initial preview - setTimeout(updatePreview, 100); - - // initial minimized option - if (${startMinimized}) { - setMinimized(true); - repaintToDock(); - void iframe.offsetWidth; - updateUI(); - } - } catch (err) { - console.error('Failed to initialize Nuxt error overlay:', err); - } -})(); -`; -} -function generateErrorOverlayHTML(html, options) { - const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join(""); - const errorPage = html.replace("", `