From ae39fdeef18f4e53eb84461263c19a6936b16846 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sun, 28 Jun 2026 11:12:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BC=9A=E8=AE=AE=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/.nuxt/components.d.ts | 2 + apps/admin/.nuxt/dev/index.mjs | 3350 +++++++++++++++++ apps/admin/.nuxt/dev/index.mjs.map | 1 + apps/admin/.nuxt/imports.d.ts | 4 +- apps/admin/.nuxt/manifest/latest.json | 1 + apps/admin/.nuxt/manifest/meta/dev.json | 1 + apps/admin/.nuxt/nitro.json | 17 + apps/admin/.nuxt/nuxt.d.ts | 4 +- apps/admin/.nuxt/nuxt.json | 9 + apps/admin/.nuxt/nuxt.lock | 9 + apps/admin/.nuxt/nuxt.node.d.ts | 4 +- apps/admin/.nuxt/tailwind/postcss.mjs | 2 +- apps/admin/.nuxt/tsconfig.app.json | 4 +- apps/admin/.nuxt/tsconfig.json | 2 +- apps/admin/.nuxt/tsconfig.shared.json | 2 +- apps/admin/.nuxt/types/build.d.ts | 2 + apps/admin/.nuxt/types/components.d.ts | 2 + apps/admin/.nuxt/types/imports.d.ts | 4 + apps/admin/.nuxt/types/plugins.d.ts | 9 +- apps/admin/.nuxt/types/runtime-config.d.ts | 2 - .../.cache/vite/client/deps/_metadata.json | 15 + .../.cache/vite/client/deps/errx.js | 51 + .../.cache/vite/client/deps/errx.js.map | 7 + .../.cache/vite/client/deps/package.json | 3 + apps/services/dump.rdb | Bin 0 -> 44652 bytes apps/services/log/console.log | 13 + apps/services/modules/echomeet/core.go | 11 + apps/services/modules/echomeet/model.go | 55 +- apps/services/modules/echomeet/model_cache.go | 30 +- deploy/console/README.md | 74 + .../{console.yaml => console.yaml.example} | 8 +- deploy/console/deploy.sh | 184 - deploy/console/dev-deploy.sh | 76 + deploy/console/docker-compose.yml | 6 +- deploy/console/env/dev.env.example | 26 - deploy/console/env/env.example | 27 + deploy/console/env/local.env.example | 23 - deploy/console/env/prod.env.example | 26 - deploy/console/prod-build.sh | 44 + deploy/console/prod-deploy.sh | 87 + deploy/voitrans/README.md | 50 +- deploy/voitrans/dev-deploy.sh | 45 +- .../env/{dev.env.example => env.example} | 0 deploy/voitrans/env/japan.env.example | 37 - deploy/voitrans/env/shanghai.env.example | 38 - deploy/voitrans/env/singapore.env.example | 37 - deploy/voitrans/prod-deploy.sh | 68 +- 47 files changed, 3993 insertions(+), 479 deletions(-) create mode 100644 apps/admin/.nuxt/dev/index.mjs create mode 100644 apps/admin/.nuxt/dev/index.mjs.map create mode 100644 apps/admin/.nuxt/manifest/latest.json create mode 100644 apps/admin/.nuxt/manifest/meta/dev.json create mode 100644 apps/admin/.nuxt/nitro.json create mode 100644 apps/admin/.nuxt/nuxt.json create mode 100644 apps/admin/.nuxt/nuxt.lock create mode 100644 apps/admin/node_modules/.cache/vite/client/deps/_metadata.json create mode 100644 apps/admin/node_modules/.cache/vite/client/deps/errx.js create mode 100644 apps/admin/node_modules/.cache/vite/client/deps/errx.js.map create mode 100644 apps/admin/node_modules/.cache/vite/client/deps/package.json create mode 100644 apps/services/dump.rdb create mode 100644 apps/services/log/console.log create mode 100644 deploy/console/README.md rename deploy/console/confs/{console.yaml => console.yaml.example} (79%) delete mode 100755 deploy/console/deploy.sh create mode 100755 deploy/console/dev-deploy.sh delete mode 100644 deploy/console/env/dev.env.example create mode 100644 deploy/console/env/env.example delete mode 100644 deploy/console/env/local.env.example delete mode 100644 deploy/console/env/prod.env.example create mode 100755 deploy/console/prod-build.sh create mode 100755 deploy/console/prod-deploy.sh rename deploy/voitrans/env/{dev.env.example => env.example} (100%) delete mode 100644 deploy/voitrans/env/japan.env.example delete mode 100644 deploy/voitrans/env/shanghai.env.example delete mode 100644 deploy/voitrans/env/singapore.env.example diff --git a/apps/admin/.nuxt/components.d.ts b/apps/admin/.nuxt/components.d.ts index ffd1397d..d57751d1 100644 --- a/apps/admin/.nuxt/components.d.ts +++ b/apps/admin/.nuxt/components.d.ts @@ -14,6 +14,7 @@ type HydrationStrategies = { type LazyComponent = DefineComponent void }> & T +export const AppLoading: typeof import("../app/components/AppLoading.vue")['default'] export const AppToast: typeof import("../app/components/AppToast.vue")['default'] export const NuxtWelcome: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/welcome.vue")['default'] export const NuxtLayout: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/nuxt-layout")['default'] @@ -39,6 +40,7 @@ export const Head: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin export const Html: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/head/runtime/components")['Html'] export const Body: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/head/runtime/components")['Body'] export const NuxtIsland: typeof import("../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/nuxt-island")['default'] +export const LazyAppLoading: LazyComponent export const LazyAppToast: LazyComponent export const LazyNuxtWelcome: LazyComponent export const LazyNuxtLayout: LazyComponent diff --git a/apps/admin/.nuxt/dev/index.mjs b/apps/admin/.nuxt/dev/index.mjs new file mode 100644 index 00000000..3172c2f2 --- /dev/null +++ b/apps/admin/.nuxt/dev/index.mjs @@ -0,0 +1,3350 @@ +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, createError, sendRedirect, proxyRequest, getRequestHeader, setResponseHeaders, setResponseStatus, send, getRequestHeaders, setResponseHeader, appendResponseHeader, getRequestURL, getResponseHeader, removeResponseHeader, getQuery as getQuery$1, readBody, createApp, createRouter as createRouter$1, toNodeListener, lazyEventHandler, getResponseStatus, getRouterParam, getResponseStatusText } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/h3@1.15.11/node_modules/h3/dist/index.mjs'; +import { Server } from 'node:http'; +import { resolve, dirname, join } from 'node:path'; +import crypto$1 from 'node:crypto'; +import { parentPort, threadId } from 'node:worker_threads'; +import { escapeHtml } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/@vue+shared@3.5.38/node_modules/@vue/shared/dist/shared.cjs.js'; +import viteNodeEntry_mjs from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/@nuxt+vite-builder@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__magicast@0_b3eceb086616bd95e9bad3803348d7ce/node_modules/@nuxt/vite-builder/dist/vite-node-entry.mjs'; +import { viteNodeFetch } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/@nuxt+vite-builder@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__magicast@0_b3eceb086616bd95e9bad3803348d7ce/node_modules/@nuxt/vite-builder/dist/vite-node.mjs'; +import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/vue-bundle-renderer@2.3.1/node_modules/vue-bundle-renderer/dist/runtime.mjs'; +import { parseURL, withoutBase, joinURL, getQuery, withQuery, withTrailingSlash, decodePath, withLeadingSlash, withoutTrailingSlash, encodePath, joinRelativeURL } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/ufo@1.6.4/node_modules/ufo/dist/index.mjs'; +import destr, { destr as destr$1 } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs'; +import { createHooks } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs'; +import { createFetch, Headers as Headers$1 } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/node.mjs'; +import { fetchNodeRequestHandler, callNodeRequestHandler } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/node-mock-http@1.0.4/node_modules/node-mock-http/dist/index.mjs'; +import { createStorage, defineDriver, prefixStorage } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/dist/index.mjs'; +import unstorage_47drivers_47fs from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/fs.mjs'; +import fsDriver from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/fs-lite.mjs'; +import lruCache from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1/node_modules/unstorage/drivers/lru-cache.mjs'; +import { digest, hash as hash$1 } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/index.mjs'; +import { klona } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/klona@2.0.6/node_modules/klona/dist/index.mjs'; +import defu, { defuFn } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/defu@6.1.7/node_modules/defu/dist/defu.mjs'; +import { snakeCase } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/scule@1.3.0/node_modules/scule/dist/index.mjs'; +import { getContext } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unctx@2.5.0/node_modules/unctx/dist/index.mjs'; +import { toRouteMatcher, createRouter } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs'; +import { readFile } from 'node:fs/promises'; +import consola, { consola as consola$1 } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs'; +import { ErrorParser } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/youch-core@0.3.3/node_modules/youch-core/build/index.js'; +import { Youch } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/youch@4.1.1/node_modules/youch/build/index.js'; +import { SourceMapConsumer } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/source-map@0.7.6/node_modules/source-map/source-map.js'; +import { AsyncLocalStorage } from 'node:async_hooks'; +import { stringify, uneval } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/devalue@5.8.1/node_modules/devalue/index.js'; +import { captureRawStackTrace, parseRawStackTrace } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/errx@0.1.0/node_modules/errx/dist/index.js'; +import { isVNode, isRef, toValue } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/vue@3.5.38_typescript@5.9.3/node_modules/vue/index.mjs'; +import _wH6JrtIxmaSoA8lCPWFnE9z4lQeXW6H5z3l5aymEQw from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/@nuxt+vite-builder@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__magicast@0_b3eceb086616bd95e9bad3803348d7ce/node_modules/@nuxt/vite-builder/dist/fix-stacktrace.mjs'; +import { promises } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname as dirname$1, resolve as resolve$1 } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.mjs'; +import { createHead as createHead$1, propsToString, renderSSRHead } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unhead@2.1.15/node_modules/unhead/dist/server.mjs'; +import { renderToString } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/vue@3.5.38_typescript@5.9.3/node_modules/vue/server-renderer/index.mjs'; +import { walkResolver } from 'file:///Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/unhead@2.1.15/node_modules/unhead/dist/utils.mjs'; + +const serverAssets = [{"baseName":"server","dir":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/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 || []) })); +} + +// @ts-check + + +/** + * @param {string} item + */ +function normalizeFsKey (item) { + const safe = item.replace(/[^\w.-]/g, '_'); + const prefix = safe.slice(0, 20); + const hash = crypto$1.createHash('sha256').update(item).digest('hex'); + return `${prefix}-${hash}` +} + +const _47Users_47liwei_47work_47go_47yunyan_47yunyan_45sas_47apps_47admin_47node_modules_47_46pnpm_47_64nuxt_43nitro_45server_644_464_468__64babel_43plugin_45syntax_45typescript_647_4629_467__64babel_43core_647_4629_467__db0_5045ebd3802f96c9dd021f3300fcdf4c_47node_modules_47_64nuxt_47nitro_45server_47dist_47runtime_47utils_47cache_45driver_46js = defineDriver( + /** + * @param {{ base?: string }} opts + */ + (opts) => { + const fs = fsDriver({ base: opts.base }); + const lru = lruCache({ max: 1000 }); + + return { + ...fs, // fall back to file system - only the bottom three methods are used in renderer + async setItem (key, value, opts) { + await Promise.all([ + fs.setItem?.(normalizeFsKey(key), value, opts), + lru.setItem?.(key, value, opts), + ]); + }, + async hasItem (key, opts) { + return await lru.hasItem(key, opts) || await fs.hasItem(normalizeFsKey(key), opts) + }, + async getItem (key, opts) { + return await lru.getItem(key, opts) || await fs.getItem(normalizeFsKey(key), opts) + }, + } + }, +); + +const storage = createStorage({}); + +storage.mount('/assets', assets$1); + +storage.mount('root', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin","watchOptions":{"ignored":[null]}})); +storage.mount('src', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/server","watchOptions":{"ignored":[null]}})); +storage.mount('cache:nuxt:payload', _47Users_47liwei_47work_47go_47yunyan_47yunyan_45sas_47apps_47admin_47node_modules_47_46pnpm_47_64nuxt_43nitro_45server_644_464_468__64babel_43plugin_45syntax_45typescript_647_4629_467__64babel_43core_647_4629_467__db0_5045ebd3802f96c9dd021f3300fcdf4c_47node_modules_47_64nuxt_47nitro_45server_47dist_47runtime_47utils_47cache_45driver_46js({"driver":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/node_modules/.pnpm/@nuxt+nitro-server@4.4.8_@babel+plugin-syntax-typescript@7.29.7_@babel+core@7.29.7__db0_5045ebd3802f96c9dd021f3300fcdf4c/node_modules/@nuxt/nitro-server/dist/runtime/utils/cache-driver.js","base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/.nuxt/cache/nuxt/payload"})); +storage.mount('build', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/.nuxt"})); +storage.mount('cache', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/.nuxt/cache"})); +storage.mount('data', unstorage_47drivers_47fs({"driver":"fs","base":"/Users/liwei/work/go/yunyan/yunyan-sas/apps/admin/.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": { + "appTitle": "Yunyan Admin" + } +}; +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 +}); + +function isPathInScope(pathname, base) { + let canonical; + try { + const pre = pathname.replace(/%2f/gi, "/").replace(/%5c/gi, "\\"); + canonical = new URL(pre, "http://_").pathname; + } catch { + return false; + } + return !base || canonical === base || canonical.startsWith(base + "/"); +} + +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) { + if (!isPathInScope(event.path.split("?")[0], strpBase)) { + throw createError({ statusCode: 400 }); + } + targetPath = withoutBase(targetPath, strpBase); + } else if (targetPath.startsWith("//")) { + targetPath = targetPath.replace(/^\/+/, "/"); + } + 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) { + if (!isPathInScope(event.path.split("?")[0], strpBase)) { + throw createError({ statusCode: 400 }); + } + targetPath = withoutBase(targetPath, strpBase); + } else if (targetPath.startsWith("//")) { + targetPath = targetPath.replace(/^\/+/, "/"); + } + 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; +} + +function isJsonRequest(event) { + + 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.data) && 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 allow-top-navigation-by-user-activation'); + + 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("", `