@andrewyang/ai-workflow-editor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nuxt/app.config.mjs +18 -0
- package/.nuxt/components.d.ts +910 -0
- package/.nuxt/dev/index.mjs +4103 -0
- package/.nuxt/dev/index.mjs.map +1 -0
- package/.nuxt/dist/server/client.manifest.mjs +4 -0
- package/.nuxt/dist/server/client.precomputed.mjs +1 -0
- package/.nuxt/dist/server/server.mjs +1 -0
- package/.nuxt/i18n-route-resources.mjs +3 -0
- package/.nuxt/imports.d.ts +43 -0
- package/.nuxt/manifest/latest.json +1 -0
- package/.nuxt/manifest/meta/dev.json +1 -0
- package/.nuxt/nitro.json +17 -0
- package/.nuxt/nuxt.d.ts +24 -0
- package/.nuxt/nuxt.json +9 -0
- package/.nuxt/schema/nuxt.schema.d.ts +17 -0
- package/.nuxt/schema/nuxt.schema.json +3 -0
- package/.nuxt/tsconfig.json +234 -0
- package/.nuxt/tsconfig.server.json +185 -0
- package/.nuxt/types/app-defaults.d.ts +7 -0
- package/.nuxt/types/app.config.d.ts +31 -0
- package/.nuxt/types/build.d.ts +29 -0
- package/.nuxt/types/builder-env.d.ts +1 -0
- package/.nuxt/types/components.d.ts +915 -0
- package/.nuxt/types/i18n-plugin.d.ts +123 -0
- package/.nuxt/types/imports.d.ts +993 -0
- package/.nuxt/types/middleware.d.ts +17 -0
- package/.nuxt/types/nitro-config.d.ts +14 -0
- package/.nuxt/types/nitro-imports.d.ts +170 -0
- package/.nuxt/types/nitro-layouts.d.ts +17 -0
- package/.nuxt/types/nitro-nuxt.d.ts +39 -0
- package/.nuxt/types/nitro-routes.d.ts +17 -0
- package/.nuxt/types/nitro.d.ts +3 -0
- package/.nuxt/types/plugins.d.ts +43 -0
- package/.nuxt/types/schema.d.ts +213 -0
- package/.nuxt/types/vue-shim.d.ts +0 -0
- package/.trae/rules/rule.md +38 -0
- package/.vscode/settings.json +5 -0
- package/nuxt.config.ts +38 -0
- package/package.json +42 -0
- package/pnpm-lock.yaml +24 -0
- package/src/app.vue +46 -0
- package/src/components/AiWorkflowEditor.vue +142 -0
- package/src/components/ai/AiChatPanel.vue +135 -0
- package/src/components/ai/AiGenerator.vue +62 -0
- package/src/components/editor/Canvas.vue +175 -0
- package/src/components/editor/FormatPanel.vue +327 -0
- package/src/components/editor/NodePanel.vue +240 -0
- package/src/components/editor/PropertyPanel.vue +348 -0
- package/src/components/editor/Toolbar.vue +49 -0
- package/src/components/editor/nodes/AiNode.vue +77 -0
- package/src/components/editor/nodes/NormalNode.vue +75 -0
- package/src/components/editor/nodes/SysmlBlockNode.vue +72 -0
- package/src/components/editor/nodes/SysmlRequirementNode.vue +72 -0
- package/src/components/editor/nodes/SysmlUseCaseNode.vue +62 -0
- package/src/composables/useAi.ts +82 -0
- package/src/i18n.config.ts +5 -0
- package/src/locales/en.json +106 -0
- package/src/locales/zh.json +106 -0
- package/src/plugins/aiWorkflowEditor.ts +6 -0
- package/src/types/ai.ts +7 -0
- package/src/types/workflow.ts +25 -0
- package/src/utils/llmAdapter.ts +46 -0
- package/tsconfig.json +3 -0
- package/uno.config.ts +15 -0
- package//345/211/215/347/253/257/345/256/232/345/210/266/345/274/200/345/217/221/357/274/232ai-workflow-editor/345/274/200/345/217/221/350/256/241/345/210/222.md +655 -0
|
@@ -0,0 +1,4103 @@
|
|
|
1
|
+
import process from 'node:process';globalThis._importMeta_={url:import.meta.url,env:process.env};import { tmpdir } from 'node:os';
|
|
2
|
+
import { Server } from 'node:http';
|
|
3
|
+
import { resolve, dirname, join } from 'node:path';
|
|
4
|
+
import nodeCrypto from 'node:crypto';
|
|
5
|
+
import { parentPort, threadId } from 'node:worker_threads';
|
|
6
|
+
import { defineEventHandler, handleCacheHeaders, splitCookiesString, createEvent, fetchWithEvent, isEvent, eventHandler, setHeaders, sendRedirect, proxyRequest, getRequestHeader, setResponseHeaders, setResponseStatus, send, getRequestHeaders, setResponseHeader, appendResponseHeader, getRequestURL, getResponseHeader, getResponseStatus, createError, getCookie, setCookie, sanitizeStatusCode, removeResponseHeader, getQuery as getQuery$1, readBody, getRouterParam, createApp, createRouter as createRouter$1, toNodeListener, lazyEventHandler, getResponseStatusText } from 'file://D:/work/ai-workflow-editor/node_modules/h3/dist/index.mjs';
|
|
7
|
+
import { escapeHtml } from 'file://D:/work/ai-workflow-editor/node_modules/@vue/shared/dist/shared.cjs.js';
|
|
8
|
+
import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file://D:/work/ai-workflow-editor/node_modules/vue-bundle-renderer/dist/runtime.mjs';
|
|
9
|
+
import { parseURL, withoutBase, joinURL, getQuery, withQuery, joinRelativeURL, parsePath, withLeadingSlash, withTrailingSlash, decodePath, withoutTrailingSlash } from 'file://D:/work/ai-workflow-editor/node_modules/ufo/dist/index.mjs';
|
|
10
|
+
import { renderToString } from 'file://D:/work/ai-workflow-editor/node_modules/vue/server-renderer/index.mjs';
|
|
11
|
+
import { klona } from 'file://D:/work/ai-workflow-editor/node_modules/klona/dist/index.mjs';
|
|
12
|
+
import defu, { defuFn, createDefu } from 'file://D:/work/ai-workflow-editor/node_modules/defu/dist/defu.mjs';
|
|
13
|
+
import destr, { destr as destr$1 } from 'file://D:/work/ai-workflow-editor/node_modules/destr/dist/index.mjs';
|
|
14
|
+
import { snakeCase } from 'file://D:/work/ai-workflow-editor/node_modules/scule/dist/index.mjs';
|
|
15
|
+
import { createHead as createHead$1, propsToString, renderSSRHead } from 'file://D:/work/ai-workflow-editor/node_modules/unhead/dist/server.mjs';
|
|
16
|
+
import { stringify, uneval } from 'file://D:/work/ai-workflow-editor/node_modules/devalue/index.js';
|
|
17
|
+
import { isVNode, isRef, toValue } from 'file://D:/work/ai-workflow-editor/node_modules/vue/index.mjs';
|
|
18
|
+
import { DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin } from 'file://D:/work/ai-workflow-editor/node_modules/unhead/dist/plugins.mjs';
|
|
19
|
+
import { createHooks } from 'file://D:/work/ai-workflow-editor/node_modules/hookable/dist/index.mjs';
|
|
20
|
+
import { createFetch, Headers as Headers$1 } from 'file://D:/work/ai-workflow-editor/node_modules/ofetch/dist/node.mjs';
|
|
21
|
+
import { fetchNodeRequestHandler, callNodeRequestHandler } from 'file://D:/work/ai-workflow-editor/node_modules/node-mock-http/dist/index.mjs';
|
|
22
|
+
import { createStorage, prefixStorage } from 'file://D:/work/ai-workflow-editor/node_modules/unstorage/dist/index.mjs';
|
|
23
|
+
import unstorage_47drivers_47fs from 'file://D:/work/ai-workflow-editor/node_modules/unstorage/drivers/fs.mjs';
|
|
24
|
+
import { digest } from 'file://D:/work/ai-workflow-editor/node_modules/ohash/dist/index.mjs';
|
|
25
|
+
import { toRouteMatcher, createRouter } from 'file://D:/work/ai-workflow-editor/node_modules/radix3/dist/index.mjs';
|
|
26
|
+
import { readFile } from 'node:fs/promises';
|
|
27
|
+
import consola, { consola as consola$1 } from 'file://D:/work/ai-workflow-editor/node_modules/consola/dist/index.mjs';
|
|
28
|
+
import { ErrorParser } from 'file://D:/work/ai-workflow-editor/node_modules/youch-core/build/index.js';
|
|
29
|
+
import { Youch } from 'file://D:/work/ai-workflow-editor/node_modules/youch/build/index.js';
|
|
30
|
+
import { SourceMapConsumer } from 'file://D:/work/ai-workflow-editor/node_modules/nitropack/node_modules/source-map/source-map.js';
|
|
31
|
+
import { createRouterMatcher } from 'file://D:/work/ai-workflow-editor/node_modules/vue-router/vue-router.node.mjs';
|
|
32
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
33
|
+
import { getContext } from 'file://D:/work/ai-workflow-editor/node_modules/unctx/dist/index.mjs';
|
|
34
|
+
import { captureRawStackTrace, parseRawStackTrace } from 'file://D:/work/ai-workflow-editor/node_modules/errx/dist/index.js';
|
|
35
|
+
import { promises } from 'node:fs';
|
|
36
|
+
import { fileURLToPath } from 'node:url';
|
|
37
|
+
import { dirname as dirname$1, resolve as resolve$1 } from 'file://D:/work/ai-workflow-editor/node_modules/pathe/dist/index.mjs';
|
|
38
|
+
import { walkResolver } from 'file://D:/work/ai-workflow-editor/node_modules/unhead/dist/utils.mjs';
|
|
39
|
+
|
|
40
|
+
const serverAssets = [{"baseName":"server","dir":"D:/work/ai-workflow-editor/src/server/assets"}];
|
|
41
|
+
|
|
42
|
+
const assets$1 = createStorage();
|
|
43
|
+
|
|
44
|
+
for (const asset of serverAssets) {
|
|
45
|
+
assets$1.mount(asset.baseName, unstorage_47drivers_47fs({ base: asset.dir, ignore: (asset?.ignore || []) }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const storage$1 = createStorage({});
|
|
49
|
+
|
|
50
|
+
storage$1.mount('/assets', assets$1);
|
|
51
|
+
|
|
52
|
+
storage$1.mount('root', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"D:/work/ai-workflow-editor","watchOptions":{"ignored":[null]}}));
|
|
53
|
+
storage$1.mount('src', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"D:/work/ai-workflow-editor/src/server","watchOptions":{"ignored":[null]}}));
|
|
54
|
+
storage$1.mount('build', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"D:/work/ai-workflow-editor/.nuxt"}));
|
|
55
|
+
storage$1.mount('cache', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"D:/work/ai-workflow-editor/.nuxt/cache"}));
|
|
56
|
+
storage$1.mount('data', unstorage_47drivers_47fs({"driver":"fs","base":"D:/work/ai-workflow-editor/.data/kv"}));
|
|
57
|
+
|
|
58
|
+
function useStorage(base = "") {
|
|
59
|
+
return base ? prefixStorage(storage$1, base) : storage$1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const Hasher = /* @__PURE__ */ (() => {
|
|
63
|
+
class Hasher2 {
|
|
64
|
+
buff = "";
|
|
65
|
+
#context = /* @__PURE__ */ new Map();
|
|
66
|
+
write(str) {
|
|
67
|
+
this.buff += str;
|
|
68
|
+
}
|
|
69
|
+
dispatch(value) {
|
|
70
|
+
const type = value === null ? "null" : typeof value;
|
|
71
|
+
return this[type](value);
|
|
72
|
+
}
|
|
73
|
+
object(object) {
|
|
74
|
+
if (object && typeof object.toJSON === "function") {
|
|
75
|
+
return this.object(object.toJSON());
|
|
76
|
+
}
|
|
77
|
+
const objString = Object.prototype.toString.call(object);
|
|
78
|
+
let objType = "";
|
|
79
|
+
const objectLength = objString.length;
|
|
80
|
+
objType = objectLength < 10 ? "unknown:[" + objString + "]" : objString.slice(8, objectLength - 1);
|
|
81
|
+
objType = objType.toLowerCase();
|
|
82
|
+
let objectNumber = null;
|
|
83
|
+
if ((objectNumber = this.#context.get(object)) === void 0) {
|
|
84
|
+
this.#context.set(object, this.#context.size);
|
|
85
|
+
} else {
|
|
86
|
+
return this.dispatch("[CIRCULAR:" + objectNumber + "]");
|
|
87
|
+
}
|
|
88
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
89
|
+
this.write("buffer:");
|
|
90
|
+
return this.write(object.toString("utf8"));
|
|
91
|
+
}
|
|
92
|
+
if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
|
|
93
|
+
if (this[objType]) {
|
|
94
|
+
this[objType](object);
|
|
95
|
+
} else {
|
|
96
|
+
this.unknown(object, objType);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
const keys = Object.keys(object).sort();
|
|
100
|
+
const extraKeys = [];
|
|
101
|
+
this.write("object:" + (keys.length + extraKeys.length) + ":");
|
|
102
|
+
const dispatchForKey = (key) => {
|
|
103
|
+
this.dispatch(key);
|
|
104
|
+
this.write(":");
|
|
105
|
+
this.dispatch(object[key]);
|
|
106
|
+
this.write(",");
|
|
107
|
+
};
|
|
108
|
+
for (const key of keys) {
|
|
109
|
+
dispatchForKey(key);
|
|
110
|
+
}
|
|
111
|
+
for (const key of extraKeys) {
|
|
112
|
+
dispatchForKey(key);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
array(arr, unordered) {
|
|
117
|
+
unordered = unordered === void 0 ? false : unordered;
|
|
118
|
+
this.write("array:" + arr.length + ":");
|
|
119
|
+
if (!unordered || arr.length <= 1) {
|
|
120
|
+
for (const entry of arr) {
|
|
121
|
+
this.dispatch(entry);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const contextAdditions = /* @__PURE__ */ new Map();
|
|
126
|
+
const entries = arr.map((entry) => {
|
|
127
|
+
const hasher = new Hasher2();
|
|
128
|
+
hasher.dispatch(entry);
|
|
129
|
+
for (const [key, value] of hasher.#context) {
|
|
130
|
+
contextAdditions.set(key, value);
|
|
131
|
+
}
|
|
132
|
+
return hasher.toString();
|
|
133
|
+
});
|
|
134
|
+
this.#context = contextAdditions;
|
|
135
|
+
entries.sort();
|
|
136
|
+
return this.array(entries, false);
|
|
137
|
+
}
|
|
138
|
+
date(date) {
|
|
139
|
+
return this.write("date:" + date.toJSON());
|
|
140
|
+
}
|
|
141
|
+
symbol(sym) {
|
|
142
|
+
return this.write("symbol:" + sym.toString());
|
|
143
|
+
}
|
|
144
|
+
unknown(value, type) {
|
|
145
|
+
this.write(type);
|
|
146
|
+
if (!value) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.write(":");
|
|
150
|
+
if (value && typeof value.entries === "function") {
|
|
151
|
+
return this.array(
|
|
152
|
+
[...value.entries()],
|
|
153
|
+
true
|
|
154
|
+
/* ordered */
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
error(err) {
|
|
159
|
+
return this.write("error:" + err.toString());
|
|
160
|
+
}
|
|
161
|
+
boolean(bool) {
|
|
162
|
+
return this.write("bool:" + bool);
|
|
163
|
+
}
|
|
164
|
+
string(string) {
|
|
165
|
+
this.write("string:" + string.length + ":");
|
|
166
|
+
this.write(string);
|
|
167
|
+
}
|
|
168
|
+
function(fn) {
|
|
169
|
+
this.write("fn:");
|
|
170
|
+
if (isNativeFunction(fn)) {
|
|
171
|
+
this.dispatch("[native]");
|
|
172
|
+
} else {
|
|
173
|
+
this.dispatch(fn.toString());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
number(number) {
|
|
177
|
+
return this.write("number:" + number);
|
|
178
|
+
}
|
|
179
|
+
null() {
|
|
180
|
+
return this.write("Null");
|
|
181
|
+
}
|
|
182
|
+
undefined() {
|
|
183
|
+
return this.write("Undefined");
|
|
184
|
+
}
|
|
185
|
+
regexp(regex) {
|
|
186
|
+
return this.write("regex:" + regex.toString());
|
|
187
|
+
}
|
|
188
|
+
arraybuffer(arr) {
|
|
189
|
+
this.write("arraybuffer:");
|
|
190
|
+
return this.dispatch(new Uint8Array(arr));
|
|
191
|
+
}
|
|
192
|
+
url(url) {
|
|
193
|
+
return this.write("url:" + url.toString());
|
|
194
|
+
}
|
|
195
|
+
map(map) {
|
|
196
|
+
this.write("map:");
|
|
197
|
+
const arr = [...map];
|
|
198
|
+
return this.array(arr, false);
|
|
199
|
+
}
|
|
200
|
+
set(set) {
|
|
201
|
+
this.write("set:");
|
|
202
|
+
const arr = [...set];
|
|
203
|
+
return this.array(arr, false);
|
|
204
|
+
}
|
|
205
|
+
bigint(number) {
|
|
206
|
+
return this.write("bigint:" + number.toString());
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const type of [
|
|
210
|
+
"uint8array",
|
|
211
|
+
"uint8clampedarray",
|
|
212
|
+
"unt8array",
|
|
213
|
+
"uint16array",
|
|
214
|
+
"unt16array",
|
|
215
|
+
"uint32array",
|
|
216
|
+
"unt32array",
|
|
217
|
+
"float32array",
|
|
218
|
+
"float64array"
|
|
219
|
+
]) {
|
|
220
|
+
Hasher2.prototype[type] = function(arr) {
|
|
221
|
+
this.write(type + ":");
|
|
222
|
+
return this.array([...arr], false);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function isNativeFunction(f) {
|
|
226
|
+
if (typeof f !== "function") {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
return Function.prototype.toString.call(f).slice(
|
|
230
|
+
-15
|
|
231
|
+
/* "[native code] }".length */
|
|
232
|
+
) === "[native code] }";
|
|
233
|
+
}
|
|
234
|
+
return Hasher2;
|
|
235
|
+
})();
|
|
236
|
+
function serialize(object) {
|
|
237
|
+
const hasher = new Hasher();
|
|
238
|
+
hasher.dispatch(object);
|
|
239
|
+
return hasher.buff;
|
|
240
|
+
}
|
|
241
|
+
function hash(value) {
|
|
242
|
+
return digest(typeof value === "string" ? value : serialize(value)).replace(/[-_]/g, "").slice(0, 10);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function defaultCacheOptions() {
|
|
246
|
+
return {
|
|
247
|
+
name: "_",
|
|
248
|
+
base: "/cache",
|
|
249
|
+
swr: true,
|
|
250
|
+
maxAge: 1
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function defineCachedFunction(fn, opts = {}) {
|
|
254
|
+
opts = { ...defaultCacheOptions(), ...opts };
|
|
255
|
+
const pending = {};
|
|
256
|
+
const group = opts.group || "nitro/functions";
|
|
257
|
+
const name = opts.name || fn.name || "_";
|
|
258
|
+
const integrity = opts.integrity || hash([fn, opts]);
|
|
259
|
+
const validate = opts.validate || ((entry) => entry.value !== void 0);
|
|
260
|
+
async function get(key, resolver, shouldInvalidateCache, event) {
|
|
261
|
+
const cacheKey = [opts.base, group, name, key + ".json"].filter(Boolean).join(":").replace(/:\/$/, ":index");
|
|
262
|
+
let entry = await useStorage().getItem(cacheKey).catch((error) => {
|
|
263
|
+
console.error(`[cache] Cache read error.`, error);
|
|
264
|
+
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
265
|
+
}) || {};
|
|
266
|
+
if (typeof entry !== "object") {
|
|
267
|
+
entry = {};
|
|
268
|
+
const error = new Error("Malformed data read from cache.");
|
|
269
|
+
console.error("[cache]", error);
|
|
270
|
+
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
271
|
+
}
|
|
272
|
+
const ttl = (opts.maxAge ?? 0) * 1e3;
|
|
273
|
+
if (ttl) {
|
|
274
|
+
entry.expires = Date.now() + ttl;
|
|
275
|
+
}
|
|
276
|
+
const expired = shouldInvalidateCache || entry.integrity !== integrity || ttl && Date.now() - (entry.mtime || 0) > ttl || validate(entry) === false;
|
|
277
|
+
const _resolve = async () => {
|
|
278
|
+
const isPending = pending[key];
|
|
279
|
+
if (!isPending) {
|
|
280
|
+
if (entry.value !== void 0 && (opts.staleMaxAge || 0) >= 0 && opts.swr === false) {
|
|
281
|
+
entry.value = void 0;
|
|
282
|
+
entry.integrity = void 0;
|
|
283
|
+
entry.mtime = void 0;
|
|
284
|
+
entry.expires = void 0;
|
|
285
|
+
}
|
|
286
|
+
pending[key] = Promise.resolve(resolver());
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
entry.value = await pending[key];
|
|
290
|
+
} catch (error) {
|
|
291
|
+
if (!isPending) {
|
|
292
|
+
delete pending[key];
|
|
293
|
+
}
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
if (!isPending) {
|
|
297
|
+
entry.mtime = Date.now();
|
|
298
|
+
entry.integrity = integrity;
|
|
299
|
+
delete pending[key];
|
|
300
|
+
if (validate(entry) !== false) {
|
|
301
|
+
let setOpts;
|
|
302
|
+
if (opts.maxAge && !opts.swr) {
|
|
303
|
+
setOpts = { ttl: opts.maxAge };
|
|
304
|
+
}
|
|
305
|
+
const promise = useStorage().setItem(cacheKey, entry, setOpts).catch((error) => {
|
|
306
|
+
console.error(`[cache] Cache write error.`, error);
|
|
307
|
+
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
308
|
+
});
|
|
309
|
+
if (event?.waitUntil) {
|
|
310
|
+
event.waitUntil(promise);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const _resolvePromise = expired ? _resolve() : Promise.resolve();
|
|
316
|
+
if (entry.value === void 0) {
|
|
317
|
+
await _resolvePromise;
|
|
318
|
+
} else if (expired && event && event.waitUntil) {
|
|
319
|
+
event.waitUntil(_resolvePromise);
|
|
320
|
+
}
|
|
321
|
+
if (opts.swr && validate(entry) !== false) {
|
|
322
|
+
_resolvePromise.catch((error) => {
|
|
323
|
+
console.error(`[cache] SWR handler error.`, error);
|
|
324
|
+
useNitroApp().captureError(error, { event, tags: ["cache"] });
|
|
325
|
+
});
|
|
326
|
+
return entry;
|
|
327
|
+
}
|
|
328
|
+
return _resolvePromise.then(() => entry);
|
|
329
|
+
}
|
|
330
|
+
return async (...args) => {
|
|
331
|
+
const shouldBypassCache = await opts.shouldBypassCache?.(...args);
|
|
332
|
+
if (shouldBypassCache) {
|
|
333
|
+
return fn(...args);
|
|
334
|
+
}
|
|
335
|
+
const key = await (opts.getKey || getKey)(...args);
|
|
336
|
+
const shouldInvalidateCache = await opts.shouldInvalidateCache?.(...args);
|
|
337
|
+
const entry = await get(
|
|
338
|
+
key,
|
|
339
|
+
() => fn(...args),
|
|
340
|
+
shouldInvalidateCache,
|
|
341
|
+
args[0] && isEvent(args[0]) ? args[0] : void 0
|
|
342
|
+
);
|
|
343
|
+
let value = entry.value;
|
|
344
|
+
if (opts.transform) {
|
|
345
|
+
value = await opts.transform(entry, ...args) || value;
|
|
346
|
+
}
|
|
347
|
+
return value;
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function cachedFunction(fn, opts = {}) {
|
|
351
|
+
return defineCachedFunction(fn, opts);
|
|
352
|
+
}
|
|
353
|
+
function getKey(...args) {
|
|
354
|
+
return args.length > 0 ? hash(args) : "";
|
|
355
|
+
}
|
|
356
|
+
function escapeKey(key) {
|
|
357
|
+
return String(key).replace(/\W/g, "");
|
|
358
|
+
}
|
|
359
|
+
function defineCachedEventHandler(handler, opts = defaultCacheOptions()) {
|
|
360
|
+
const variableHeaderNames = (opts.varies || []).filter(Boolean).map((h) => h.toLowerCase()).sort();
|
|
361
|
+
const _opts = {
|
|
362
|
+
...opts,
|
|
363
|
+
getKey: async (event) => {
|
|
364
|
+
const customKey = await opts.getKey?.(event);
|
|
365
|
+
if (customKey) {
|
|
366
|
+
return escapeKey(customKey);
|
|
367
|
+
}
|
|
368
|
+
const _path = event.node.req.originalUrl || event.node.req.url || event.path;
|
|
369
|
+
let _pathname;
|
|
370
|
+
try {
|
|
371
|
+
_pathname = escapeKey(decodeURI(parseURL(_path).pathname)).slice(0, 16) || "index";
|
|
372
|
+
} catch {
|
|
373
|
+
_pathname = "-";
|
|
374
|
+
}
|
|
375
|
+
const _hashedPath = `${_pathname}.${hash(_path)}`;
|
|
376
|
+
const _headers = variableHeaderNames.map((header) => [header, event.node.req.headers[header]]).map(([name, value]) => `${escapeKey(name)}.${hash(value)}`);
|
|
377
|
+
return [_hashedPath, ..._headers].join(":");
|
|
378
|
+
},
|
|
379
|
+
validate: (entry) => {
|
|
380
|
+
if (!entry.value) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
if (entry.value.code >= 400) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
if (entry.value.body === void 0) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
if (entry.value.headers.etag === "undefined" || entry.value.headers["last-modified"] === "undefined") {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
return true;
|
|
393
|
+
},
|
|
394
|
+
group: opts.group || "nitro/handlers",
|
|
395
|
+
integrity: opts.integrity || hash([handler, opts])
|
|
396
|
+
};
|
|
397
|
+
const _cachedHandler = cachedFunction(
|
|
398
|
+
async (incomingEvent) => {
|
|
399
|
+
const variableHeaders = {};
|
|
400
|
+
for (const header of variableHeaderNames) {
|
|
401
|
+
const value = incomingEvent.node.req.headers[header];
|
|
402
|
+
if (value !== void 0) {
|
|
403
|
+
variableHeaders[header] = value;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const reqProxy = cloneWithProxy(incomingEvent.node.req, {
|
|
407
|
+
headers: variableHeaders
|
|
408
|
+
});
|
|
409
|
+
const resHeaders = {};
|
|
410
|
+
let _resSendBody;
|
|
411
|
+
const resProxy = cloneWithProxy(incomingEvent.node.res, {
|
|
412
|
+
statusCode: 200,
|
|
413
|
+
writableEnded: false,
|
|
414
|
+
writableFinished: false,
|
|
415
|
+
headersSent: false,
|
|
416
|
+
closed: false,
|
|
417
|
+
getHeader(name) {
|
|
418
|
+
return resHeaders[name];
|
|
419
|
+
},
|
|
420
|
+
setHeader(name, value) {
|
|
421
|
+
resHeaders[name] = value;
|
|
422
|
+
return this;
|
|
423
|
+
},
|
|
424
|
+
getHeaderNames() {
|
|
425
|
+
return Object.keys(resHeaders);
|
|
426
|
+
},
|
|
427
|
+
hasHeader(name) {
|
|
428
|
+
return name in resHeaders;
|
|
429
|
+
},
|
|
430
|
+
removeHeader(name) {
|
|
431
|
+
delete resHeaders[name];
|
|
432
|
+
},
|
|
433
|
+
getHeaders() {
|
|
434
|
+
return resHeaders;
|
|
435
|
+
},
|
|
436
|
+
end(chunk, arg2, arg3) {
|
|
437
|
+
if (typeof chunk === "string") {
|
|
438
|
+
_resSendBody = chunk;
|
|
439
|
+
}
|
|
440
|
+
if (typeof arg2 === "function") {
|
|
441
|
+
arg2();
|
|
442
|
+
}
|
|
443
|
+
if (typeof arg3 === "function") {
|
|
444
|
+
arg3();
|
|
445
|
+
}
|
|
446
|
+
return this;
|
|
447
|
+
},
|
|
448
|
+
write(chunk, arg2, arg3) {
|
|
449
|
+
if (typeof chunk === "string") {
|
|
450
|
+
_resSendBody = chunk;
|
|
451
|
+
}
|
|
452
|
+
if (typeof arg2 === "function") {
|
|
453
|
+
arg2(void 0);
|
|
454
|
+
}
|
|
455
|
+
if (typeof arg3 === "function") {
|
|
456
|
+
arg3();
|
|
457
|
+
}
|
|
458
|
+
return true;
|
|
459
|
+
},
|
|
460
|
+
writeHead(statusCode, headers2) {
|
|
461
|
+
this.statusCode = statusCode;
|
|
462
|
+
if (headers2) {
|
|
463
|
+
if (Array.isArray(headers2) || typeof headers2 === "string") {
|
|
464
|
+
throw new TypeError("Raw headers is not supported.");
|
|
465
|
+
}
|
|
466
|
+
for (const header in headers2) {
|
|
467
|
+
const value = headers2[header];
|
|
468
|
+
if (value !== void 0) {
|
|
469
|
+
this.setHeader(
|
|
470
|
+
header,
|
|
471
|
+
value
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return this;
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
const event = createEvent(reqProxy, resProxy);
|
|
480
|
+
event.fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
|
|
481
|
+
fetch: useNitroApp().localFetch
|
|
482
|
+
});
|
|
483
|
+
event.$fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, {
|
|
484
|
+
fetch: globalThis.$fetch
|
|
485
|
+
});
|
|
486
|
+
event.waitUntil = incomingEvent.waitUntil;
|
|
487
|
+
event.context = incomingEvent.context;
|
|
488
|
+
event.context.cache = {
|
|
489
|
+
options: _opts
|
|
490
|
+
};
|
|
491
|
+
const body = await handler(event) || _resSendBody;
|
|
492
|
+
const headers = event.node.res.getHeaders();
|
|
493
|
+
headers.etag = String(
|
|
494
|
+
headers.Etag || headers.etag || `W/"${hash(body)}"`
|
|
495
|
+
);
|
|
496
|
+
headers["last-modified"] = String(
|
|
497
|
+
headers["Last-Modified"] || headers["last-modified"] || (/* @__PURE__ */ new Date()).toUTCString()
|
|
498
|
+
);
|
|
499
|
+
const cacheControl = [];
|
|
500
|
+
if (opts.swr) {
|
|
501
|
+
if (opts.maxAge) {
|
|
502
|
+
cacheControl.push(`s-maxage=${opts.maxAge}`);
|
|
503
|
+
}
|
|
504
|
+
if (opts.staleMaxAge) {
|
|
505
|
+
cacheControl.push(`stale-while-revalidate=${opts.staleMaxAge}`);
|
|
506
|
+
} else {
|
|
507
|
+
cacheControl.push("stale-while-revalidate");
|
|
508
|
+
}
|
|
509
|
+
} else if (opts.maxAge) {
|
|
510
|
+
cacheControl.push(`max-age=${opts.maxAge}`);
|
|
511
|
+
}
|
|
512
|
+
if (cacheControl.length > 0) {
|
|
513
|
+
headers["cache-control"] = cacheControl.join(", ");
|
|
514
|
+
}
|
|
515
|
+
const cacheEntry = {
|
|
516
|
+
code: event.node.res.statusCode,
|
|
517
|
+
headers,
|
|
518
|
+
body
|
|
519
|
+
};
|
|
520
|
+
return cacheEntry;
|
|
521
|
+
},
|
|
522
|
+
_opts
|
|
523
|
+
);
|
|
524
|
+
return defineEventHandler(async (event) => {
|
|
525
|
+
if (opts.headersOnly) {
|
|
526
|
+
if (handleCacheHeaders(event, { maxAge: opts.maxAge })) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
return handler(event);
|
|
530
|
+
}
|
|
531
|
+
const response = await _cachedHandler(
|
|
532
|
+
event
|
|
533
|
+
);
|
|
534
|
+
if (event.node.res.headersSent || event.node.res.writableEnded) {
|
|
535
|
+
return response.body;
|
|
536
|
+
}
|
|
537
|
+
if (handleCacheHeaders(event, {
|
|
538
|
+
modifiedTime: new Date(response.headers["last-modified"]),
|
|
539
|
+
etag: response.headers.etag,
|
|
540
|
+
maxAge: opts.maxAge
|
|
541
|
+
})) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
event.node.res.statusCode = response.code;
|
|
545
|
+
for (const name in response.headers) {
|
|
546
|
+
const value = response.headers[name];
|
|
547
|
+
if (name === "set-cookie") {
|
|
548
|
+
event.node.res.appendHeader(
|
|
549
|
+
name,
|
|
550
|
+
splitCookiesString(value)
|
|
551
|
+
);
|
|
552
|
+
} else {
|
|
553
|
+
if (value !== void 0) {
|
|
554
|
+
event.node.res.setHeader(name, value);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return response.body;
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
function cloneWithProxy(obj, overrides) {
|
|
562
|
+
return new Proxy(obj, {
|
|
563
|
+
get(target, property, receiver) {
|
|
564
|
+
if (property in overrides) {
|
|
565
|
+
return overrides[property];
|
|
566
|
+
}
|
|
567
|
+
return Reflect.get(target, property, receiver);
|
|
568
|
+
},
|
|
569
|
+
set(target, property, value, receiver) {
|
|
570
|
+
if (property in overrides) {
|
|
571
|
+
overrides[property] = value;
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
return Reflect.set(target, property, value, receiver);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
const cachedEventHandler = defineCachedEventHandler;
|
|
579
|
+
|
|
580
|
+
const inlineAppConfig = {
|
|
581
|
+
"nuxt": {}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
const appConfig = defuFn(inlineAppConfig);
|
|
587
|
+
|
|
588
|
+
function getEnv(key, opts) {
|
|
589
|
+
const envKey = snakeCase(key).toUpperCase();
|
|
590
|
+
return destr(
|
|
591
|
+
process.env[opts.prefix + envKey] ?? process.env[opts.altPrefix + envKey]
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
function _isObject(input) {
|
|
595
|
+
return typeof input === "object" && !Array.isArray(input);
|
|
596
|
+
}
|
|
597
|
+
function applyEnv(obj, opts, parentKey = "") {
|
|
598
|
+
for (const key in obj) {
|
|
599
|
+
const subKey = parentKey ? `${parentKey}_${key}` : key;
|
|
600
|
+
const envValue = getEnv(subKey, opts);
|
|
601
|
+
if (_isObject(obj[key])) {
|
|
602
|
+
if (_isObject(envValue)) {
|
|
603
|
+
obj[key] = { ...obj[key], ...envValue };
|
|
604
|
+
applyEnv(obj[key], opts, subKey);
|
|
605
|
+
} else if (envValue === void 0) {
|
|
606
|
+
applyEnv(obj[key], opts, subKey);
|
|
607
|
+
} else {
|
|
608
|
+
obj[key] = envValue ?? obj[key];
|
|
609
|
+
}
|
|
610
|
+
} else {
|
|
611
|
+
obj[key] = envValue ?? obj[key];
|
|
612
|
+
}
|
|
613
|
+
if (opts.envExpansion && typeof obj[key] === "string") {
|
|
614
|
+
obj[key] = _expandFromEnv(obj[key]);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return obj;
|
|
618
|
+
}
|
|
619
|
+
const envExpandRx = /\{\{([^{}]*)\}\}/g;
|
|
620
|
+
function _expandFromEnv(value) {
|
|
621
|
+
return value.replace(envExpandRx, (match, key) => {
|
|
622
|
+
return process.env[key] || match;
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const _inlineRuntimeConfig = {
|
|
627
|
+
"app": {
|
|
628
|
+
"baseURL": "/",
|
|
629
|
+
"buildId": "dev",
|
|
630
|
+
"buildAssetsDir": "/_nuxt/",
|
|
631
|
+
"cdnURL": ""
|
|
632
|
+
},
|
|
633
|
+
"nitro": {
|
|
634
|
+
"envPrefix": "NUXT_",
|
|
635
|
+
"routeRules": {
|
|
636
|
+
"/__nuxt_error": {
|
|
637
|
+
"cache": false
|
|
638
|
+
},
|
|
639
|
+
"/_nuxt/builds/meta/**": {
|
|
640
|
+
"headers": {
|
|
641
|
+
"cache-control": "public, max-age=31536000, immutable"
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
"/_nuxt/builds/**": {
|
|
645
|
+
"headers": {
|
|
646
|
+
"cache-control": "public, max-age=1, immutable"
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
"public": {
|
|
652
|
+
"i18n": {
|
|
653
|
+
"baseUrl": "",
|
|
654
|
+
"defaultLocale": "zh",
|
|
655
|
+
"rootRedirect": "",
|
|
656
|
+
"redirectStatusCode": 302,
|
|
657
|
+
"skipSettingLocaleOnNavigate": false,
|
|
658
|
+
"locales": [
|
|
659
|
+
{
|
|
660
|
+
"code": "zh",
|
|
661
|
+
"name": "中文",
|
|
662
|
+
"language": ""
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"code": "en",
|
|
666
|
+
"name": "English",
|
|
667
|
+
"language": ""
|
|
668
|
+
}
|
|
669
|
+
],
|
|
670
|
+
"detectBrowserLanguage": {
|
|
671
|
+
"alwaysRedirect": false,
|
|
672
|
+
"cookieCrossOrigin": false,
|
|
673
|
+
"cookieDomain": "",
|
|
674
|
+
"cookieKey": "i18n_redirected",
|
|
675
|
+
"cookieSecure": false,
|
|
676
|
+
"fallbackLocale": "",
|
|
677
|
+
"redirectOn": "root",
|
|
678
|
+
"useCookie": true
|
|
679
|
+
},
|
|
680
|
+
"experimental": {
|
|
681
|
+
"localeDetector": "",
|
|
682
|
+
"typedPages": true,
|
|
683
|
+
"typedOptionsAndMessages": false,
|
|
684
|
+
"alternateLinkCanonicalQueries": true,
|
|
685
|
+
"devCache": false,
|
|
686
|
+
"cacheLifetime": "",
|
|
687
|
+
"stripMessagesPayload": false,
|
|
688
|
+
"preload": false,
|
|
689
|
+
"strictSeo": false,
|
|
690
|
+
"nitroContextDetection": true,
|
|
691
|
+
"httpCacheDuration": 10
|
|
692
|
+
},
|
|
693
|
+
"domainLocales": {
|
|
694
|
+
"zh": {
|
|
695
|
+
"domain": ""
|
|
696
|
+
},
|
|
697
|
+
"en": {
|
|
698
|
+
"domain": ""
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
const envOptions = {
|
|
705
|
+
prefix: "NITRO_",
|
|
706
|
+
altPrefix: _inlineRuntimeConfig.nitro.envPrefix ?? process.env.NITRO_ENV_PREFIX ?? "_",
|
|
707
|
+
envExpansion: _inlineRuntimeConfig.nitro.envExpansion ?? process.env.NITRO_ENV_EXPANSION ?? false
|
|
708
|
+
};
|
|
709
|
+
const _sharedRuntimeConfig = _deepFreeze(
|
|
710
|
+
applyEnv(klona(_inlineRuntimeConfig), envOptions)
|
|
711
|
+
);
|
|
712
|
+
function useRuntimeConfig(event) {
|
|
713
|
+
if (!event) {
|
|
714
|
+
return _sharedRuntimeConfig;
|
|
715
|
+
}
|
|
716
|
+
if (event.context.nitro.runtimeConfig) {
|
|
717
|
+
return event.context.nitro.runtimeConfig;
|
|
718
|
+
}
|
|
719
|
+
const runtimeConfig = klona(_inlineRuntimeConfig);
|
|
720
|
+
applyEnv(runtimeConfig, envOptions);
|
|
721
|
+
event.context.nitro.runtimeConfig = runtimeConfig;
|
|
722
|
+
return runtimeConfig;
|
|
723
|
+
}
|
|
724
|
+
_deepFreeze(klona(appConfig));
|
|
725
|
+
function _deepFreeze(object) {
|
|
726
|
+
const propNames = Object.getOwnPropertyNames(object);
|
|
727
|
+
for (const name of propNames) {
|
|
728
|
+
const value = object[name];
|
|
729
|
+
if (value && typeof value === "object") {
|
|
730
|
+
_deepFreeze(value);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return Object.freeze(object);
|
|
734
|
+
}
|
|
735
|
+
new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
736
|
+
get: (_, prop) => {
|
|
737
|
+
console.warn(
|
|
738
|
+
"Please use `useRuntimeConfig()` instead of accessing config directly."
|
|
739
|
+
);
|
|
740
|
+
const runtimeConfig = useRuntimeConfig();
|
|
741
|
+
if (prop in runtimeConfig) {
|
|
742
|
+
return runtimeConfig[prop];
|
|
743
|
+
}
|
|
744
|
+
return void 0;
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
const config = useRuntimeConfig();
|
|
749
|
+
const _routeRulesMatcher = toRouteMatcher(
|
|
750
|
+
createRouter({ routes: config.nitro.routeRules })
|
|
751
|
+
);
|
|
752
|
+
function createRouteRulesHandler(ctx) {
|
|
753
|
+
return eventHandler((event) => {
|
|
754
|
+
const routeRules = getRouteRules(event);
|
|
755
|
+
if (routeRules.headers) {
|
|
756
|
+
setHeaders(event, routeRules.headers);
|
|
757
|
+
}
|
|
758
|
+
if (routeRules.redirect) {
|
|
759
|
+
let target = routeRules.redirect.to;
|
|
760
|
+
if (target.endsWith("/**")) {
|
|
761
|
+
let targetPath = event.path;
|
|
762
|
+
const strpBase = routeRules.redirect._redirectStripBase;
|
|
763
|
+
if (strpBase) {
|
|
764
|
+
targetPath = withoutBase(targetPath, strpBase);
|
|
765
|
+
}
|
|
766
|
+
target = joinURL(target.slice(0, -3), targetPath);
|
|
767
|
+
} else if (event.path.includes("?")) {
|
|
768
|
+
const query = getQuery(event.path);
|
|
769
|
+
target = withQuery(target, query);
|
|
770
|
+
}
|
|
771
|
+
return sendRedirect(event, target, routeRules.redirect.statusCode);
|
|
772
|
+
}
|
|
773
|
+
if (routeRules.proxy) {
|
|
774
|
+
let target = routeRules.proxy.to;
|
|
775
|
+
if (target.endsWith("/**")) {
|
|
776
|
+
let targetPath = event.path;
|
|
777
|
+
const strpBase = routeRules.proxy._proxyStripBase;
|
|
778
|
+
if (strpBase) {
|
|
779
|
+
targetPath = withoutBase(targetPath, strpBase);
|
|
780
|
+
}
|
|
781
|
+
target = joinURL(target.slice(0, -3), targetPath);
|
|
782
|
+
} else if (event.path.includes("?")) {
|
|
783
|
+
const query = getQuery(event.path);
|
|
784
|
+
target = withQuery(target, query);
|
|
785
|
+
}
|
|
786
|
+
return proxyRequest(event, target, {
|
|
787
|
+
fetch: ctx.localFetch,
|
|
788
|
+
...routeRules.proxy
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
function getRouteRules(event) {
|
|
794
|
+
event.context._nitro = event.context._nitro || {};
|
|
795
|
+
if (!event.context._nitro.routeRules) {
|
|
796
|
+
event.context._nitro.routeRules = getRouteRulesForPath(
|
|
797
|
+
withoutBase(event.path.split("?")[0], useRuntimeConfig().app.baseURL)
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
return event.context._nitro.routeRules;
|
|
801
|
+
}
|
|
802
|
+
function getRouteRulesForPath(path) {
|
|
803
|
+
return defu({}, ..._routeRulesMatcher.matchAll(path).reverse());
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
function _captureError(error, type) {
|
|
807
|
+
console.error(`[${type}]`, error);
|
|
808
|
+
useNitroApp().captureError(error, { tags: [type] });
|
|
809
|
+
}
|
|
810
|
+
function trapUnhandledNodeErrors() {
|
|
811
|
+
process.on(
|
|
812
|
+
"unhandledRejection",
|
|
813
|
+
(error) => _captureError(error, "unhandledRejection")
|
|
814
|
+
);
|
|
815
|
+
process.on(
|
|
816
|
+
"uncaughtException",
|
|
817
|
+
(error) => _captureError(error, "uncaughtException")
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
function joinHeaders(value) {
|
|
821
|
+
return Array.isArray(value) ? value.join(", ") : String(value);
|
|
822
|
+
}
|
|
823
|
+
function normalizeFetchResponse(response) {
|
|
824
|
+
if (!response.headers.has("set-cookie")) {
|
|
825
|
+
return response;
|
|
826
|
+
}
|
|
827
|
+
return new Response(response.body, {
|
|
828
|
+
status: response.status,
|
|
829
|
+
statusText: response.statusText,
|
|
830
|
+
headers: normalizeCookieHeaders(response.headers)
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
function normalizeCookieHeader(header = "") {
|
|
834
|
+
return splitCookiesString(joinHeaders(header));
|
|
835
|
+
}
|
|
836
|
+
function normalizeCookieHeaders(headers) {
|
|
837
|
+
const outgoingHeaders = new Headers();
|
|
838
|
+
for (const [name, header] of headers) {
|
|
839
|
+
if (name === "set-cookie") {
|
|
840
|
+
for (const cookie of normalizeCookieHeader(header)) {
|
|
841
|
+
outgoingHeaders.append("set-cookie", cookie);
|
|
842
|
+
}
|
|
843
|
+
} else {
|
|
844
|
+
outgoingHeaders.set(name, joinHeaders(header));
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
return outgoingHeaders;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Nitro internal functions extracted from https://github.com/nitrojs/nitro/blob/v2/src/runtime/internal/utils.ts
|
|
852
|
+
*/
|
|
853
|
+
function isJsonRequest(event) {
|
|
854
|
+
// If the client specifically requests HTML, then avoid classifying as JSON.
|
|
855
|
+
if (hasReqHeader(event, "accept", "text/html")) {
|
|
856
|
+
return false;
|
|
857
|
+
}
|
|
858
|
+
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");
|
|
859
|
+
}
|
|
860
|
+
function hasReqHeader(event, name, includes) {
|
|
861
|
+
const value = getRequestHeader(event, name);
|
|
862
|
+
return value && typeof value === "string" && value.toLowerCase().includes(includes);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const iframeStorageBridge = (nonce) => `
|
|
866
|
+
(function () {
|
|
867
|
+
const NONCE = ${JSON.stringify(nonce)};
|
|
868
|
+
const memoryStore = Object.create(null);
|
|
869
|
+
|
|
870
|
+
const post = (type, payload) => {
|
|
871
|
+
window.parent.postMessage({ type, nonce: NONCE, ...payload }, '*');
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
const isValid = (data) => data && data.nonce === NONCE;
|
|
875
|
+
|
|
876
|
+
const mockStorage = {
|
|
877
|
+
getItem(key) {
|
|
878
|
+
return Object.hasOwn(memoryStore, key)
|
|
879
|
+
? memoryStore[key]
|
|
880
|
+
: null;
|
|
881
|
+
},
|
|
882
|
+
setItem(key, value) {
|
|
883
|
+
const v = String(value);
|
|
884
|
+
memoryStore[key] = v;
|
|
885
|
+
post('storage-set', { key, value: v });
|
|
886
|
+
},
|
|
887
|
+
removeItem(key) {
|
|
888
|
+
delete memoryStore[key];
|
|
889
|
+
post('storage-remove', { key });
|
|
890
|
+
},
|
|
891
|
+
clear() {
|
|
892
|
+
for (const key of Object.keys(memoryStore))
|
|
893
|
+
delete memoryStore[key];
|
|
894
|
+
post('storage-clear', {});
|
|
895
|
+
},
|
|
896
|
+
key(index) {
|
|
897
|
+
const keys = Object.keys(memoryStore);
|
|
898
|
+
return keys[index] ?? null;
|
|
899
|
+
},
|
|
900
|
+
get length() {
|
|
901
|
+
return Object.keys(memoryStore).length;
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
const defineLocalStorage = () => {
|
|
906
|
+
try {
|
|
907
|
+
Object.defineProperty(window, 'localStorage', {
|
|
908
|
+
value: mockStorage,
|
|
909
|
+
writable: false,
|
|
910
|
+
configurable: true
|
|
911
|
+
});
|
|
912
|
+
} catch {
|
|
913
|
+
window.localStorage = mockStorage;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
defineLocalStorage();
|
|
918
|
+
|
|
919
|
+
window.addEventListener('message', (event) => {
|
|
920
|
+
const data = event.data;
|
|
921
|
+
if (!isValid(data) || data.type !== 'storage-sync-data') return;
|
|
922
|
+
|
|
923
|
+
const incoming = data.data || {};
|
|
924
|
+
for (const key of Object.keys(incoming))
|
|
925
|
+
memoryStore[key] = incoming[key];
|
|
926
|
+
|
|
927
|
+
if (typeof window.initTheme === 'function')
|
|
928
|
+
window.initTheme();
|
|
929
|
+
window.dispatchEvent(new Event('storage-ready'));
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
// Clipboard API is unavailable in data: URL iframe, so we use postMessage
|
|
933
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
934
|
+
window.copyErrorMessage = function(button) {
|
|
935
|
+
post('clipboard-copy', { text: button.dataset.errorText });
|
|
936
|
+
button.classList.add('copied');
|
|
937
|
+
setTimeout(function() { button.classList.remove('copied'); }, 2000);
|
|
938
|
+
};
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
post('storage-sync-request', {});
|
|
942
|
+
})();
|
|
943
|
+
`;
|
|
944
|
+
const parentStorageBridge = (nonce) => `
|
|
945
|
+
(function () {
|
|
946
|
+
const host = document.querySelector('nuxt-error-overlay');
|
|
947
|
+
if (!host) return;
|
|
948
|
+
|
|
949
|
+
const NONCE = ${JSON.stringify(nonce)};
|
|
950
|
+
const isValid = (data) => data && data.nonce === NONCE;
|
|
951
|
+
|
|
952
|
+
// Handle clipboard copy from iframe
|
|
953
|
+
window.addEventListener('message', function(e) {
|
|
954
|
+
if (isValid(e) && e.data.type === 'clipboard-copy') {
|
|
955
|
+
navigator.clipboard.writeText(e.data.text).catch(function() {});
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
const collectLocalStorage = () => {
|
|
960
|
+
const all = {};
|
|
961
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
962
|
+
const k = localStorage.key(i);
|
|
963
|
+
if (k != null) all[k] = localStorage.getItem(k);
|
|
964
|
+
}
|
|
965
|
+
return all;
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
const attachWhenReady = () => {
|
|
969
|
+
const root = host.shadowRoot;
|
|
970
|
+
if (!root)
|
|
971
|
+
return false;
|
|
972
|
+
const iframe = root.getElementById('frame');
|
|
973
|
+
if (!iframe || !iframe.contentWindow)
|
|
974
|
+
return false;
|
|
975
|
+
|
|
976
|
+
const handlers = {
|
|
977
|
+
'storage-set': (d) => localStorage.setItem(d.key, d.value),
|
|
978
|
+
'storage-remove': (d) => localStorage.removeItem(d.key),
|
|
979
|
+
'storage-clear': () => localStorage.clear(),
|
|
980
|
+
'storage-sync-request': () => {
|
|
981
|
+
iframe.contentWindow.postMessage({
|
|
982
|
+
type: 'storage-sync-data',
|
|
983
|
+
data: collectLocalStorage(),
|
|
984
|
+
nonce: NONCE
|
|
985
|
+
}, '*');
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
window.addEventListener('message', (event) => {
|
|
990
|
+
const data = event.data;
|
|
991
|
+
if (!isValid(data)) return;
|
|
992
|
+
const fn = handlers[data.type];
|
|
993
|
+
if (fn) fn(data);
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
return true;
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
if (attachWhenReady())
|
|
1000
|
+
return;
|
|
1001
|
+
|
|
1002
|
+
const obs = new MutationObserver(() => {
|
|
1003
|
+
if (attachWhenReady())
|
|
1004
|
+
obs.disconnect();
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
obs.observe(host, { childList: true, subtree: true });
|
|
1008
|
+
})();
|
|
1009
|
+
`;
|
|
1010
|
+
const errorCSS = `
|
|
1011
|
+
:host {
|
|
1012
|
+
--preview-width: 240px;
|
|
1013
|
+
--preview-height: 180px;
|
|
1014
|
+
--base-width: 1200px;
|
|
1015
|
+
--base-height: 900px;
|
|
1016
|
+
--z-base: 999999998;
|
|
1017
|
+
--error-pip-left: auto;
|
|
1018
|
+
--error-pip-top: auto;
|
|
1019
|
+
--error-pip-right: 5px;
|
|
1020
|
+
--error-pip-bottom: 5px;
|
|
1021
|
+
--error-pip-origin: bottom right;
|
|
1022
|
+
--app-preview-left: auto;
|
|
1023
|
+
--app-preview-top: auto;
|
|
1024
|
+
--app-preview-right: 5px;
|
|
1025
|
+
--app-preview-bottom: 5px;
|
|
1026
|
+
all: initial;
|
|
1027
|
+
display: contents;
|
|
1028
|
+
}
|
|
1029
|
+
.sr-only {
|
|
1030
|
+
position: absolute;
|
|
1031
|
+
width: 1px;
|
|
1032
|
+
height: 1px;
|
|
1033
|
+
padding: 0;
|
|
1034
|
+
margin: -1px;
|
|
1035
|
+
overflow: hidden;
|
|
1036
|
+
clip: rect(0, 0, 0, 0);
|
|
1037
|
+
white-space: nowrap;
|
|
1038
|
+
border-width: 0;
|
|
1039
|
+
}
|
|
1040
|
+
#frame {
|
|
1041
|
+
position: fixed;
|
|
1042
|
+
left: 0;
|
|
1043
|
+
top: 0;
|
|
1044
|
+
width: 100vw;
|
|
1045
|
+
height: 100vh;
|
|
1046
|
+
border: none;
|
|
1047
|
+
z-index: var(--z-base);
|
|
1048
|
+
}
|
|
1049
|
+
#frame[inert] {
|
|
1050
|
+
left: var(--error-pip-left);
|
|
1051
|
+
top: var(--error-pip-top);
|
|
1052
|
+
right: var(--error-pip-right);
|
|
1053
|
+
bottom: var(--error-pip-bottom);
|
|
1054
|
+
width: var(--base-width);
|
|
1055
|
+
height: var(--base-height);
|
|
1056
|
+
transform: scale(calc(240 / 1200));
|
|
1057
|
+
transform-origin: var(--error-pip-origin);
|
|
1058
|
+
overflow: hidden;
|
|
1059
|
+
border-radius: calc(1200 * 8px / 240);
|
|
1060
|
+
}
|
|
1061
|
+
#preview {
|
|
1062
|
+
position: fixed;
|
|
1063
|
+
left: var(--app-preview-left);
|
|
1064
|
+
top: var(--app-preview-top);
|
|
1065
|
+
right: var(--app-preview-right);
|
|
1066
|
+
bottom: var(--app-preview-bottom);
|
|
1067
|
+
width: var(--preview-width);
|
|
1068
|
+
height: var(--preview-height);
|
|
1069
|
+
overflow: hidden;
|
|
1070
|
+
border-radius: 6px;
|
|
1071
|
+
pointer-events: none;
|
|
1072
|
+
z-index: var(--z-base);
|
|
1073
|
+
background: white;
|
|
1074
|
+
display: none;
|
|
1075
|
+
}
|
|
1076
|
+
#preview iframe {
|
|
1077
|
+
transform-origin: var(--error-pip-origin);
|
|
1078
|
+
}
|
|
1079
|
+
#frame:not([inert]) + #preview {
|
|
1080
|
+
display: block;
|
|
1081
|
+
}
|
|
1082
|
+
#toggle {
|
|
1083
|
+
position: fixed;
|
|
1084
|
+
left: var(--app-preview-left);
|
|
1085
|
+
top: var(--app-preview-top);
|
|
1086
|
+
right: calc(var(--app-preview-right) - 3px);
|
|
1087
|
+
bottom: calc(var(--app-preview-bottom) - 3px);
|
|
1088
|
+
width: var(--preview-width);
|
|
1089
|
+
height: var(--preview-height);
|
|
1090
|
+
background: none;
|
|
1091
|
+
border: 3px solid #00DC82;
|
|
1092
|
+
border-radius: 8px;
|
|
1093
|
+
cursor: pointer;
|
|
1094
|
+
opacity: 0.8;
|
|
1095
|
+
transition: opacity 0.2s, box-shadow 0.2s;
|
|
1096
|
+
z-index: calc(var(--z-base) + 1);
|
|
1097
|
+
display: flex;
|
|
1098
|
+
align-items: center;
|
|
1099
|
+
justify-content: center;
|
|
1100
|
+
}
|
|
1101
|
+
#toggle:hover,
|
|
1102
|
+
#toggle:focus {
|
|
1103
|
+
opacity: 1;
|
|
1104
|
+
box-shadow: 0 0 20px rgba(0, 220, 130, 0.6);
|
|
1105
|
+
}
|
|
1106
|
+
#toggle:focus-visible {
|
|
1107
|
+
outline: 3px solid #00DC82;
|
|
1108
|
+
outline-offset: 0;
|
|
1109
|
+
box-shadow: 0 0 24px rgba(0, 220, 130, 0.8);
|
|
1110
|
+
}
|
|
1111
|
+
#frame[inert] ~ #toggle {
|
|
1112
|
+
left: var(--error-pip-left);
|
|
1113
|
+
top: var(--error-pip-top);
|
|
1114
|
+
right: calc(var(--error-pip-right) - 3px);
|
|
1115
|
+
bottom: calc(var(--error-pip-bottom) - 3px);
|
|
1116
|
+
cursor: grab;
|
|
1117
|
+
}
|
|
1118
|
+
:host(.dragging) #frame[inert] ~ #toggle {
|
|
1119
|
+
cursor: grabbing;
|
|
1120
|
+
}
|
|
1121
|
+
#frame:not([inert]) ~ #toggle,
|
|
1122
|
+
#frame:not([inert]) + #preview {
|
|
1123
|
+
cursor: grab;
|
|
1124
|
+
}
|
|
1125
|
+
:host(.dragging-preview) #frame:not([inert]) ~ #toggle,
|
|
1126
|
+
:host(.dragging-preview) #frame:not([inert]) + #preview {
|
|
1127
|
+
cursor: grabbing;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
#pip-close {
|
|
1131
|
+
position: absolute;
|
|
1132
|
+
top: 6px;
|
|
1133
|
+
right: 6px;
|
|
1134
|
+
width: 24px;
|
|
1135
|
+
height: 24px;
|
|
1136
|
+
border-radius: 50%;
|
|
1137
|
+
border: none;
|
|
1138
|
+
background: rgba(0, 0, 0, 0.75);
|
|
1139
|
+
color: #fff;
|
|
1140
|
+
font-size: 16px;
|
|
1141
|
+
line-height: 1;
|
|
1142
|
+
display: inline-flex;
|
|
1143
|
+
align-items: center;
|
|
1144
|
+
justify-content: center;
|
|
1145
|
+
cursor: pointer;
|
|
1146
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
1147
|
+
pointer-events: auto;
|
|
1148
|
+
}
|
|
1149
|
+
#pip-close:focus-visible {
|
|
1150
|
+
outline: 2px solid #00DC82;
|
|
1151
|
+
outline-offset: 2px;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
#pip-restore {
|
|
1155
|
+
position: fixed;
|
|
1156
|
+
right: 16px;
|
|
1157
|
+
bottom: 16px;
|
|
1158
|
+
padding: 8px 14px;
|
|
1159
|
+
border-radius: 999px;
|
|
1160
|
+
border: 2px solid #00DC82;
|
|
1161
|
+
background: #111;
|
|
1162
|
+
color: #fff;
|
|
1163
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
1164
|
+
font-size: 14px;
|
|
1165
|
+
display: inline-flex;
|
|
1166
|
+
align-items: center;
|
|
1167
|
+
gap: 6px;
|
|
1168
|
+
z-index: calc(var(--z-base) + 2);
|
|
1169
|
+
cursor: grab;
|
|
1170
|
+
}
|
|
1171
|
+
#pip-restore:focus-visible {
|
|
1172
|
+
outline: 2px solid #00DC82;
|
|
1173
|
+
outline-offset: 2px;
|
|
1174
|
+
}
|
|
1175
|
+
:host(.dragging-restore) #pip-restore {
|
|
1176
|
+
cursor: grabbing;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
#frame[hidden],
|
|
1180
|
+
#toggle[hidden],
|
|
1181
|
+
#preview[hidden],
|
|
1182
|
+
#pip-restore[hidden],
|
|
1183
|
+
#pip-close[hidden] {
|
|
1184
|
+
display: none !important;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1188
|
+
#toggle {
|
|
1189
|
+
transition: none;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
`;
|
|
1193
|
+
function webComponentScript(base64HTML, startMinimized) {
|
|
1194
|
+
return `
|
|
1195
|
+
(function () {
|
|
1196
|
+
try {
|
|
1197
|
+
// =========================
|
|
1198
|
+
// Host + Shadow
|
|
1199
|
+
// =========================
|
|
1200
|
+
const host = document.querySelector('nuxt-error-overlay');
|
|
1201
|
+
if (!host)
|
|
1202
|
+
return;
|
|
1203
|
+
const shadow = host.attachShadow({ mode: 'open' });
|
|
1204
|
+
|
|
1205
|
+
// =========================
|
|
1206
|
+
// DOM helpers
|
|
1207
|
+
// =========================
|
|
1208
|
+
const el = (tag) => document.createElement(tag);
|
|
1209
|
+
const on = (node, type, fn, opts) => node.addEventListener(type, fn, opts);
|
|
1210
|
+
const hide = (node, v) => node.toggleAttribute('hidden', !!v);
|
|
1211
|
+
const setVar = (name, value) => host.style.setProperty(name, value);
|
|
1212
|
+
const unsetVar = (name) => host.style.removeProperty(name);
|
|
1213
|
+
|
|
1214
|
+
// =========================
|
|
1215
|
+
// Create DOM
|
|
1216
|
+
// =========================
|
|
1217
|
+
const style = el('style');
|
|
1218
|
+
style.textContent = ${JSON.stringify(errorCSS)};
|
|
1219
|
+
|
|
1220
|
+
const iframe = el('iframe');
|
|
1221
|
+
iframe.id = 'frame';
|
|
1222
|
+
iframe.src = 'data:text/html;base64,${base64HTML}';
|
|
1223
|
+
iframe.title = 'Detailed error stack trace';
|
|
1224
|
+
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
1225
|
+
|
|
1226
|
+
const preview = el('div');
|
|
1227
|
+
preview.id = 'preview';
|
|
1228
|
+
|
|
1229
|
+
const toggle = el('div');
|
|
1230
|
+
toggle.id = 'toggle';
|
|
1231
|
+
toggle.setAttribute('aria-expanded', 'true');
|
|
1232
|
+
toggle.setAttribute('role', 'button');
|
|
1233
|
+
toggle.setAttribute('tabindex', '0');
|
|
1234
|
+
toggle.innerHTML = '<span class="sr-only">Toggle detailed error view</span>';
|
|
1235
|
+
|
|
1236
|
+
const liveRegion = el('div');
|
|
1237
|
+
liveRegion.setAttribute('role', 'status');
|
|
1238
|
+
liveRegion.setAttribute('aria-live', 'polite');
|
|
1239
|
+
liveRegion.className = 'sr-only';
|
|
1240
|
+
|
|
1241
|
+
const pipCloseButton = el('button');
|
|
1242
|
+
pipCloseButton.id = 'pip-close';
|
|
1243
|
+
pipCloseButton.setAttribute('type', 'button');
|
|
1244
|
+
pipCloseButton.setAttribute('aria-label', 'Hide error preview overlay');
|
|
1245
|
+
pipCloseButton.innerHTML = '×';
|
|
1246
|
+
pipCloseButton.hidden = true;
|
|
1247
|
+
toggle.appendChild(pipCloseButton);
|
|
1248
|
+
|
|
1249
|
+
const pipRestoreButton = el('button');
|
|
1250
|
+
pipRestoreButton.id = 'pip-restore';
|
|
1251
|
+
pipRestoreButton.setAttribute('type', 'button');
|
|
1252
|
+
pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
|
|
1253
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error overlay</span>';
|
|
1254
|
+
pipRestoreButton.hidden = true;
|
|
1255
|
+
|
|
1256
|
+
// Order matters: #frame + #preview adjacency
|
|
1257
|
+
shadow.appendChild(style);
|
|
1258
|
+
shadow.appendChild(liveRegion);
|
|
1259
|
+
shadow.appendChild(iframe);
|
|
1260
|
+
shadow.appendChild(preview);
|
|
1261
|
+
shadow.appendChild(toggle);
|
|
1262
|
+
shadow.appendChild(pipRestoreButton);
|
|
1263
|
+
|
|
1264
|
+
// =========================
|
|
1265
|
+
// Constants / keys
|
|
1266
|
+
// =========================
|
|
1267
|
+
const POS_KEYS = {
|
|
1268
|
+
position: 'nuxt-error-overlay:position',
|
|
1269
|
+
hiddenPretty: 'nuxt-error-overlay:error-pip:hidden',
|
|
1270
|
+
hiddenPreview: 'nuxt-error-overlay:app-preview:hidden'
|
|
1271
|
+
};
|
|
1272
|
+
|
|
1273
|
+
const CSS_VARS = {
|
|
1274
|
+
pip: {
|
|
1275
|
+
left: '--error-pip-left',
|
|
1276
|
+
top: '--error-pip-top',
|
|
1277
|
+
right: '--error-pip-right',
|
|
1278
|
+
bottom: '--error-pip-bottom'
|
|
1279
|
+
},
|
|
1280
|
+
preview: {
|
|
1281
|
+
left: '--app-preview-left',
|
|
1282
|
+
top: '--app-preview-top',
|
|
1283
|
+
right: '--app-preview-right',
|
|
1284
|
+
bottom: '--app-preview-bottom'
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
const MIN_GAP = 5;
|
|
1289
|
+
const DRAG_THRESHOLD = 2;
|
|
1290
|
+
|
|
1291
|
+
// =========================
|
|
1292
|
+
// Local storage safe access + state
|
|
1293
|
+
// =========================
|
|
1294
|
+
let storageReady = true;
|
|
1295
|
+
let isPrettyHidden = false;
|
|
1296
|
+
let isPreviewHidden = false;
|
|
1297
|
+
|
|
1298
|
+
const safeGet = (k) => {
|
|
1299
|
+
try {
|
|
1300
|
+
return localStorage.getItem(k);
|
|
1301
|
+
} catch {
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
const safeSet = (k, v) => {
|
|
1307
|
+
if (!storageReady)
|
|
1308
|
+
return;
|
|
1309
|
+
try {
|
|
1310
|
+
localStorage.setItem(k, v);
|
|
1311
|
+
} catch {}
|
|
1312
|
+
};
|
|
1313
|
+
|
|
1314
|
+
// =========================
|
|
1315
|
+
// Sizing helpers
|
|
1316
|
+
// =========================
|
|
1317
|
+
const vvSize = () => {
|
|
1318
|
+
const v = window.visualViewport;
|
|
1319
|
+
return v ? { w: v.width, h: v.height } : { w: window.innerWidth, h: window.innerHeight };
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
const previewSize = () => {
|
|
1323
|
+
const styles = getComputedStyle(host);
|
|
1324
|
+
const w = parseFloat(styles.getPropertyValue('--preview-width')) || 240;
|
|
1325
|
+
const h = parseFloat(styles.getPropertyValue('--preview-height')) || 180;
|
|
1326
|
+
return { w, h };
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
const sizeForTarget = (target) => {
|
|
1330
|
+
if (!target)
|
|
1331
|
+
return previewSize();
|
|
1332
|
+
const rect = target.getBoundingClientRect();
|
|
1333
|
+
if (rect.width && rect.height)
|
|
1334
|
+
return { w: rect.width, h: rect.height };
|
|
1335
|
+
return previewSize();
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1338
|
+
// =========================
|
|
1339
|
+
// Dock model + offset/alignment calculations
|
|
1340
|
+
// =========================
|
|
1341
|
+
const dock = { edge: null, offset: null, align: null, gap: null };
|
|
1342
|
+
|
|
1343
|
+
const maxOffsetFor = (edge, size) => {
|
|
1344
|
+
const vv = vvSize();
|
|
1345
|
+
if (edge === 'left' || edge === 'right')
|
|
1346
|
+
return Math.max(MIN_GAP, vv.h - size.h - MIN_GAP);
|
|
1347
|
+
return Math.max(MIN_GAP, vv.w - size.w - MIN_GAP);
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
const clampOffset = (edge, value, size) => {
|
|
1351
|
+
const max = maxOffsetFor(edge, size);
|
|
1352
|
+
return Math.min(Math.max(value, MIN_GAP), max);
|
|
1353
|
+
};
|
|
1354
|
+
|
|
1355
|
+
const updateDockAlignment = (size) => {
|
|
1356
|
+
if (!dock.edge || dock.offset == null)
|
|
1357
|
+
return;
|
|
1358
|
+
const max = maxOffsetFor(dock.edge, size);
|
|
1359
|
+
if (dock.offset <= max / 2) {
|
|
1360
|
+
dock.align = 'start';
|
|
1361
|
+
dock.gap = dock.offset;
|
|
1362
|
+
} else {
|
|
1363
|
+
dock.align = 'end';
|
|
1364
|
+
dock.gap = Math.max(0, max - dock.offset);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1368
|
+
const appliedOffsetFor = (size) => {
|
|
1369
|
+
if (!dock.edge || dock.offset == null)
|
|
1370
|
+
return null;
|
|
1371
|
+
const max = maxOffsetFor(dock.edge, size);
|
|
1372
|
+
|
|
1373
|
+
if (dock.align === 'end' && typeof dock.gap === 'number') {
|
|
1374
|
+
return clampOffset(dock.edge, max - dock.gap, size);
|
|
1375
|
+
}
|
|
1376
|
+
if (dock.align === 'start' && typeof dock.gap === 'number') {
|
|
1377
|
+
return clampOffset(dock.edge, dock.gap, size);
|
|
1378
|
+
}
|
|
1379
|
+
return clampOffset(dock.edge, dock.offset, size);
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
const nearestEdgeAt = (x, y) => {
|
|
1383
|
+
const { w, h } = vvSize();
|
|
1384
|
+
const d = { left: x, right: w - x, top: y, bottom: h - y };
|
|
1385
|
+
return Object.keys(d).reduce((a, b) => (d[a] < d[b] ? a : b));
|
|
1386
|
+
};
|
|
1387
|
+
|
|
1388
|
+
const cornerDefaultDock = () => {
|
|
1389
|
+
const vv = vvSize();
|
|
1390
|
+
const size = previewSize();
|
|
1391
|
+
const offset = Math.max(MIN_GAP, vv.w - size.w - MIN_GAP);
|
|
1392
|
+
return { edge: 'bottom', offset };
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
const currentTransformOrigin = () => {
|
|
1396
|
+
if (!dock.edge) return null;
|
|
1397
|
+
if (dock.edge === 'left' || dock.edge === 'top')
|
|
1398
|
+
return 'top left';
|
|
1399
|
+
if (dock.edge === 'right')
|
|
1400
|
+
return 'top right';
|
|
1401
|
+
return 'bottom left';
|
|
1402
|
+
};
|
|
1403
|
+
|
|
1404
|
+
// =========================
|
|
1405
|
+
// Persist / load dock
|
|
1406
|
+
// =========================
|
|
1407
|
+
const loadDock = () => {
|
|
1408
|
+
const raw = safeGet(POS_KEYS.position);
|
|
1409
|
+
if (!raw)
|
|
1410
|
+
return;
|
|
1411
|
+
try {
|
|
1412
|
+
const parsed = JSON.parse(raw);
|
|
1413
|
+
const { edge, offset, align, gap } = parsed || {};
|
|
1414
|
+
if (!['left', 'right', 'top', 'bottom'].includes(edge))
|
|
1415
|
+
return;
|
|
1416
|
+
if (typeof offset !== 'number')
|
|
1417
|
+
return;
|
|
1418
|
+
|
|
1419
|
+
dock.edge = edge;
|
|
1420
|
+
dock.offset = clampOffset(edge, offset, previewSize());
|
|
1421
|
+
dock.align = align === 'start' || align === 'end' ? align : null;
|
|
1422
|
+
dock.gap = typeof gap === 'number' ? gap : null;
|
|
1423
|
+
|
|
1424
|
+
if (!dock.align || dock.gap == null)
|
|
1425
|
+
updateDockAlignment(previewSize());
|
|
1426
|
+
} catch {}
|
|
1427
|
+
};
|
|
1428
|
+
|
|
1429
|
+
const persistDock = () => {
|
|
1430
|
+
if (!dock.edge || dock.offset == null)
|
|
1431
|
+
return;
|
|
1432
|
+
safeSet(POS_KEYS.position, JSON.stringify({
|
|
1433
|
+
edge: dock.edge,
|
|
1434
|
+
offset: dock.offset,
|
|
1435
|
+
align: dock.align,
|
|
1436
|
+
gap: dock.gap
|
|
1437
|
+
}));
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
// =========================
|
|
1441
|
+
// Apply dock
|
|
1442
|
+
// =========================
|
|
1443
|
+
const dockToVars = (vars) => ({
|
|
1444
|
+
set: (side, v) => host.style.setProperty(vars[side], v),
|
|
1445
|
+
clear: (side) => host.style.removeProperty(vars[side])
|
|
1446
|
+
});
|
|
1447
|
+
|
|
1448
|
+
const dockToEl = (node) => ({
|
|
1449
|
+
set: (side, v) => { node.style[side] = v; },
|
|
1450
|
+
clear: (side) => { node.style[side] = ''; }
|
|
1451
|
+
});
|
|
1452
|
+
|
|
1453
|
+
const applyDock = (target, size, opts) => {
|
|
1454
|
+
if (!dock.edge || dock.offset == null) {
|
|
1455
|
+
target.clear('left');
|
|
1456
|
+
target.clear('top');
|
|
1457
|
+
target.clear('right');
|
|
1458
|
+
target.clear('bottom');
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
target.set('left', 'auto');
|
|
1463
|
+
target.set('top', 'auto');
|
|
1464
|
+
target.set('right', 'auto');
|
|
1465
|
+
target.set('bottom', 'auto');
|
|
1466
|
+
|
|
1467
|
+
const applied = appliedOffsetFor(size);
|
|
1468
|
+
|
|
1469
|
+
if (dock.edge === 'left') {
|
|
1470
|
+
target.set('left', MIN_GAP + 'px');
|
|
1471
|
+
target.set('top', applied + 'px');
|
|
1472
|
+
} else if (dock.edge === 'right') {
|
|
1473
|
+
target.set('right', MIN_GAP + 'px');
|
|
1474
|
+
target.set('top', applied + 'px');
|
|
1475
|
+
} else if (dock.edge === 'top') {
|
|
1476
|
+
target.set('top', MIN_GAP + 'px');
|
|
1477
|
+
target.set('left', applied + 'px');
|
|
1478
|
+
} else {
|
|
1479
|
+
target.set('bottom', MIN_GAP + 'px');
|
|
1480
|
+
target.set('left', applied + 'px');
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
if (!opts || opts.persist !== false)
|
|
1484
|
+
persistDock();
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
const applyDockAll = (opts) => {
|
|
1488
|
+
applyDock(dockToVars(CSS_VARS.pip), previewSize(), opts);
|
|
1489
|
+
applyDock(dockToVars(CSS_VARS.preview), previewSize(), opts);
|
|
1490
|
+
applyDock(dockToEl(pipRestoreButton), sizeForTarget(pipRestoreButton), opts);
|
|
1491
|
+
};
|
|
1492
|
+
|
|
1493
|
+
const repaintToDock = () => {
|
|
1494
|
+
if (!dock.edge || dock.offset == null)
|
|
1495
|
+
return;
|
|
1496
|
+
const origin = currentTransformOrigin();
|
|
1497
|
+
if (origin)
|
|
1498
|
+
setVar('--error-pip-origin', origin);
|
|
1499
|
+
else
|
|
1500
|
+
unsetVar('--error-pip-origin');
|
|
1501
|
+
applyDockAll({ persist: false });
|
|
1502
|
+
};
|
|
1503
|
+
|
|
1504
|
+
// =========================
|
|
1505
|
+
// Hidden state + UI
|
|
1506
|
+
// =========================
|
|
1507
|
+
const loadHidden = () => {
|
|
1508
|
+
const rawPretty = safeGet(POS_KEYS.hiddenPretty);
|
|
1509
|
+
if (rawPretty != null)
|
|
1510
|
+
isPrettyHidden = rawPretty === '1' || rawPretty === 'true';
|
|
1511
|
+
const rawPreview = safeGet(POS_KEYS.hiddenPreview);
|
|
1512
|
+
if (rawPreview != null)
|
|
1513
|
+
isPreviewHidden = rawPreview === '1' || rawPreview === 'true';
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
const setPrettyHidden = (v) => {
|
|
1517
|
+
isPrettyHidden = !!v;
|
|
1518
|
+
safeSet(POS_KEYS.hiddenPretty, isPrettyHidden ? '1' : '0');
|
|
1519
|
+
updateUI();
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
const setPreviewHidden = (v) => {
|
|
1523
|
+
isPreviewHidden = !!v;
|
|
1524
|
+
safeSet(POS_KEYS.hiddenPreview, isPreviewHidden ? '1' : '0');
|
|
1525
|
+
updateUI();
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
const isMinimized = () => iframe.hasAttribute('inert');
|
|
1529
|
+
|
|
1530
|
+
const setMinimized = (v) => {
|
|
1531
|
+
if (v) {
|
|
1532
|
+
iframe.setAttribute('inert', '');
|
|
1533
|
+
toggle.setAttribute('aria-expanded', 'false');
|
|
1534
|
+
} else {
|
|
1535
|
+
iframe.removeAttribute('inert');
|
|
1536
|
+
toggle.setAttribute('aria-expanded', 'true');
|
|
1537
|
+
}
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
const setRestoreLabel = (kind) => {
|
|
1541
|
+
if (kind === 'pretty') {
|
|
1542
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error overlay</span>';
|
|
1543
|
+
pipRestoreButton.setAttribute('aria-label', 'Show error overlay');
|
|
1544
|
+
} else {
|
|
1545
|
+
pipRestoreButton.innerHTML = '<span aria-hidden="true">⟲</span><span>Show error page</span>';
|
|
1546
|
+
pipRestoreButton.setAttribute('aria-label', 'Show error page');
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
|
|
1550
|
+
const updateUI = () => {
|
|
1551
|
+
const minimized = isMinimized();
|
|
1552
|
+
const showPiP = minimized && !isPrettyHidden;
|
|
1553
|
+
const showPreview = !minimized && !isPreviewHidden;
|
|
1554
|
+
const pipHiddenByUser = minimized && isPrettyHidden;
|
|
1555
|
+
const previewHiddenByUser = !minimized && isPreviewHidden;
|
|
1556
|
+
const showToggle = minimized ? showPiP : showPreview;
|
|
1557
|
+
const showRestore = pipHiddenByUser || previewHiddenByUser;
|
|
1558
|
+
|
|
1559
|
+
hide(iframe, pipHiddenByUser);
|
|
1560
|
+
hide(preview, !showPreview);
|
|
1561
|
+
hide(toggle, !showToggle);
|
|
1562
|
+
hide(pipCloseButton, !showToggle);
|
|
1563
|
+
hide(pipRestoreButton, !showRestore);
|
|
1564
|
+
|
|
1565
|
+
pipCloseButton.setAttribute('aria-label', minimized ? 'Hide error overlay' : 'Hide error page preview');
|
|
1566
|
+
|
|
1567
|
+
if (pipHiddenByUser)
|
|
1568
|
+
setRestoreLabel('pretty');
|
|
1569
|
+
else if (previewHiddenByUser)
|
|
1570
|
+
setRestoreLabel('preview');
|
|
1571
|
+
|
|
1572
|
+
host.classList.toggle('pip-hidden', isPrettyHidden);
|
|
1573
|
+
host.classList.toggle('preview-hidden', isPreviewHidden);
|
|
1574
|
+
};
|
|
1575
|
+
|
|
1576
|
+
// =========================
|
|
1577
|
+
// Preview snapshot
|
|
1578
|
+
// =========================
|
|
1579
|
+
const updatePreview = () => {
|
|
1580
|
+
try {
|
|
1581
|
+
let previewIframe = preview.querySelector('iframe');
|
|
1582
|
+
if (!previewIframe) {
|
|
1583
|
+
previewIframe = el('iframe');
|
|
1584
|
+
previewIframe.style.cssText = 'width: 1200px; height: 900px; transform: scale(0.2); transform-origin: top left; border: none;';
|
|
1585
|
+
previewIframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
1586
|
+
preview.appendChild(previewIframe);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
const doctype = document.doctype ? '<!DOCTYPE ' + document.doctype.name + '>' : '';
|
|
1590
|
+
const cleanedHTML = document.documentElement.outerHTML
|
|
1591
|
+
.replace(/<nuxt-error-overlay[^>]*>.*?<\\/nuxt-error-overlay>/gs, '')
|
|
1592
|
+
.replace(/<script[^>]*>.*?<\\/script>/gs, '');
|
|
1593
|
+
|
|
1594
|
+
const iframeDoc = previewIframe.contentDocument || previewIframe.contentWindow.document;
|
|
1595
|
+
iframeDoc.open();
|
|
1596
|
+
iframeDoc.write(doctype + cleanedHTML);
|
|
1597
|
+
iframeDoc.close();
|
|
1598
|
+
} catch (err) {
|
|
1599
|
+
console.error('Failed to update preview:', err);
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
|
|
1603
|
+
// =========================
|
|
1604
|
+
// View toggling
|
|
1605
|
+
// =========================
|
|
1606
|
+
const toggleView = () => {
|
|
1607
|
+
if (isMinimized()) {
|
|
1608
|
+
updatePreview();
|
|
1609
|
+
setMinimized(false);
|
|
1610
|
+
liveRegion.textContent = 'Showing detailed error view';
|
|
1611
|
+
setTimeout(() => {
|
|
1612
|
+
try {
|
|
1613
|
+
iframe.contentWindow.focus();
|
|
1614
|
+
} catch {}
|
|
1615
|
+
}, 100);
|
|
1616
|
+
} else {
|
|
1617
|
+
setMinimized(true);
|
|
1618
|
+
liveRegion.textContent = 'Showing error page';
|
|
1619
|
+
repaintToDock();
|
|
1620
|
+
void iframe.offsetWidth;
|
|
1621
|
+
}
|
|
1622
|
+
updateUI();
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
// =========================
|
|
1626
|
+
// Dragging (unified, rAF throttled)
|
|
1627
|
+
// =========================
|
|
1628
|
+
let drag = null;
|
|
1629
|
+
let rafId = null;
|
|
1630
|
+
let suppressToggleClick = false;
|
|
1631
|
+
let suppressRestoreClick = false;
|
|
1632
|
+
|
|
1633
|
+
const beginDrag = (e) => {
|
|
1634
|
+
if (drag)
|
|
1635
|
+
return;
|
|
1636
|
+
|
|
1637
|
+
if (!dock.edge || dock.offset == null) {
|
|
1638
|
+
const def = cornerDefaultDock();
|
|
1639
|
+
dock.edge = def.edge;
|
|
1640
|
+
dock.offset = def.offset;
|
|
1641
|
+
updateDockAlignment(previewSize());
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
const isRestoreTarget = e.currentTarget === pipRestoreButton;
|
|
1645
|
+
|
|
1646
|
+
drag = {
|
|
1647
|
+
kind: isRestoreTarget ? 'restore' : (isMinimized() ? 'pip' : 'preview'),
|
|
1648
|
+
pointerId: e.pointerId,
|
|
1649
|
+
startX: e.clientX,
|
|
1650
|
+
startY: e.clientY,
|
|
1651
|
+
lastX: e.clientX,
|
|
1652
|
+
lastY: e.clientY,
|
|
1653
|
+
moved: false,
|
|
1654
|
+
target: e.currentTarget
|
|
1655
|
+
};
|
|
1656
|
+
|
|
1657
|
+
drag.target.setPointerCapture(e.pointerId);
|
|
1658
|
+
|
|
1659
|
+
if (drag.kind === 'restore')
|
|
1660
|
+
host.classList.add('dragging-restore');
|
|
1661
|
+
else
|
|
1662
|
+
host.classList.add(drag.kind === 'pip' ? 'dragging' : 'dragging-preview');
|
|
1663
|
+
|
|
1664
|
+
e.preventDefault();
|
|
1665
|
+
};
|
|
1666
|
+
|
|
1667
|
+
const moveDrag = (e) => {
|
|
1668
|
+
if (!drag || drag.pointerId !== e.pointerId)
|
|
1669
|
+
return;
|
|
1670
|
+
|
|
1671
|
+
drag.lastX = e.clientX;
|
|
1672
|
+
drag.lastY = e.clientY;
|
|
1673
|
+
|
|
1674
|
+
const dx = drag.lastX - drag.startX;
|
|
1675
|
+
const dy = drag.lastY - drag.startY;
|
|
1676
|
+
|
|
1677
|
+
if (!drag.moved && (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD)) {
|
|
1678
|
+
drag.moved = true;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
if (!drag.moved)
|
|
1682
|
+
return;
|
|
1683
|
+
if (rafId)
|
|
1684
|
+
return;
|
|
1685
|
+
|
|
1686
|
+
rafId = requestAnimationFrame(() => {
|
|
1687
|
+
rafId = null;
|
|
1688
|
+
|
|
1689
|
+
const edge = nearestEdgeAt(drag.lastX, drag.lastY);
|
|
1690
|
+
const size = sizeForTarget(drag.target);
|
|
1691
|
+
|
|
1692
|
+
let offset;
|
|
1693
|
+
if (edge === 'left' || edge === 'right') {
|
|
1694
|
+
const top = drag.lastY - (size.h / 2);
|
|
1695
|
+
offset = clampOffset(edge, Math.round(top), size);
|
|
1696
|
+
} else {
|
|
1697
|
+
const left = drag.lastX - (size.w / 2);
|
|
1698
|
+
offset = clampOffset(edge, Math.round(left), size);
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
dock.edge = edge;
|
|
1702
|
+
dock.offset = offset;
|
|
1703
|
+
updateDockAlignment(size);
|
|
1704
|
+
|
|
1705
|
+
const origin = currentTransformOrigin();
|
|
1706
|
+
setVar('--error-pip-origin', origin || 'bottom right');
|
|
1707
|
+
|
|
1708
|
+
applyDockAll({ persist: false });
|
|
1709
|
+
});
|
|
1710
|
+
};
|
|
1711
|
+
|
|
1712
|
+
const endDrag = (e) => {
|
|
1713
|
+
if (!drag || drag.pointerId !== e.pointerId)
|
|
1714
|
+
return;
|
|
1715
|
+
|
|
1716
|
+
const endedKind = drag.kind;
|
|
1717
|
+
drag.target.releasePointerCapture(e.pointerId);
|
|
1718
|
+
|
|
1719
|
+
if (endedKind === 'restore')
|
|
1720
|
+
host.classList.remove('dragging-restore');
|
|
1721
|
+
else
|
|
1722
|
+
host.classList.remove(endedKind === 'pip' ? 'dragging' : 'dragging-preview');
|
|
1723
|
+
|
|
1724
|
+
const didMove = drag.moved;
|
|
1725
|
+
drag = null;
|
|
1726
|
+
|
|
1727
|
+
if (didMove) {
|
|
1728
|
+
persistDock();
|
|
1729
|
+
if (endedKind === 'restore')
|
|
1730
|
+
suppressRestoreClick = true;
|
|
1731
|
+
else
|
|
1732
|
+
suppressToggleClick = true;
|
|
1733
|
+
e.preventDefault();
|
|
1734
|
+
e.stopPropagation();
|
|
1735
|
+
}
|
|
1736
|
+
};
|
|
1737
|
+
|
|
1738
|
+
const bindDragTarget = (node) => {
|
|
1739
|
+
on(node, 'pointerdown', beginDrag);
|
|
1740
|
+
on(node, 'pointermove', moveDrag);
|
|
1741
|
+
on(node, 'pointerup', endDrag);
|
|
1742
|
+
on(node, 'pointercancel', endDrag);
|
|
1743
|
+
};
|
|
1744
|
+
|
|
1745
|
+
bindDragTarget(toggle);
|
|
1746
|
+
bindDragTarget(pipRestoreButton);
|
|
1747
|
+
|
|
1748
|
+
// =========================
|
|
1749
|
+
// Events (toggle / close / restore)
|
|
1750
|
+
// =========================
|
|
1751
|
+
on(toggle, 'click', (e) => {
|
|
1752
|
+
if (suppressToggleClick) {
|
|
1753
|
+
e.preventDefault();
|
|
1754
|
+
suppressToggleClick = false;
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
toggleView();
|
|
1758
|
+
});
|
|
1759
|
+
|
|
1760
|
+
on(toggle, 'keydown', (e) => {
|
|
1761
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
1762
|
+
e.preventDefault();
|
|
1763
|
+
toggleView();
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
|
|
1767
|
+
on(pipCloseButton, 'click', (e) => {
|
|
1768
|
+
e.preventDefault();
|
|
1769
|
+
e.stopPropagation();
|
|
1770
|
+
if (isMinimized())
|
|
1771
|
+
setPrettyHidden(true);
|
|
1772
|
+
else
|
|
1773
|
+
setPreviewHidden(true);
|
|
1774
|
+
});
|
|
1775
|
+
|
|
1776
|
+
on(pipCloseButton, 'pointerdown', (e) => {
|
|
1777
|
+
e.stopPropagation();
|
|
1778
|
+
});
|
|
1779
|
+
|
|
1780
|
+
on(pipRestoreButton, 'click', (e) => {
|
|
1781
|
+
if (suppressRestoreClick) {
|
|
1782
|
+
e.preventDefault();
|
|
1783
|
+
suppressRestoreClick = false;
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
e.preventDefault();
|
|
1787
|
+
e.stopPropagation();
|
|
1788
|
+
if (isMinimized())
|
|
1789
|
+
setPrettyHidden(false);
|
|
1790
|
+
else
|
|
1791
|
+
setPreviewHidden(false);
|
|
1792
|
+
});
|
|
1793
|
+
|
|
1794
|
+
// =========================
|
|
1795
|
+
// Lifecycle: load / sync / repaint
|
|
1796
|
+
// =========================
|
|
1797
|
+
const loadState = () => {
|
|
1798
|
+
loadDock();
|
|
1799
|
+
loadHidden();
|
|
1800
|
+
|
|
1801
|
+
if (isPrettyHidden && !isMinimized())
|
|
1802
|
+
setMinimized(true);
|
|
1803
|
+
|
|
1804
|
+
updateUI();
|
|
1805
|
+
repaintToDock();
|
|
1806
|
+
};
|
|
1807
|
+
|
|
1808
|
+
loadState();
|
|
1809
|
+
|
|
1810
|
+
on(window, 'storage-ready', () => {
|
|
1811
|
+
storageReady = true;
|
|
1812
|
+
loadState();
|
|
1813
|
+
});
|
|
1814
|
+
|
|
1815
|
+
const onViewportChange = () => repaintToDock();
|
|
1816
|
+
|
|
1817
|
+
on(window, 'resize', onViewportChange);
|
|
1818
|
+
|
|
1819
|
+
if (window.visualViewport) {
|
|
1820
|
+
on(window.visualViewport, 'resize', onViewportChange);
|
|
1821
|
+
on(window.visualViewport, 'scroll', onViewportChange);
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
// initial preview
|
|
1825
|
+
setTimeout(updatePreview, 100);
|
|
1826
|
+
|
|
1827
|
+
// initial minimized option
|
|
1828
|
+
if (${startMinimized}) {
|
|
1829
|
+
setMinimized(true);
|
|
1830
|
+
repaintToDock();
|
|
1831
|
+
void iframe.offsetWidth;
|
|
1832
|
+
updateUI();
|
|
1833
|
+
}
|
|
1834
|
+
} catch (err) {
|
|
1835
|
+
console.error('Failed to initialize Nuxt error overlay:', err);
|
|
1836
|
+
}
|
|
1837
|
+
})();
|
|
1838
|
+
`;
|
|
1839
|
+
}
|
|
1840
|
+
function generateErrorOverlayHTML(html, options) {
|
|
1841
|
+
const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
1842
|
+
const errorPage = html.replace("<head>", `<head><script>${iframeStorageBridge(nonce)}<\/script>`);
|
|
1843
|
+
const base64HTML = Buffer.from(errorPage, "utf8").toString("base64");
|
|
1844
|
+
return `
|
|
1845
|
+
<script>${parentStorageBridge(nonce)}<\/script>
|
|
1846
|
+
<nuxt-error-overlay></nuxt-error-overlay>
|
|
1847
|
+
<script>${webComponentScript(base64HTML, options?.startMinimized ?? false)}<\/script>
|
|
1848
|
+
`;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
const errorHandler$0 = (async function errorhandler(error, event, { defaultHandler }) {
|
|
1852
|
+
if (event.handled || isJsonRequest(event)) {
|
|
1853
|
+
// let Nitro handle JSON errors
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
// invoke default Nitro error handler (which will log appropriately if required)
|
|
1857
|
+
const defaultRes = await defaultHandler(error, event, { json: true });
|
|
1858
|
+
// let Nitro handle redirect if appropriate
|
|
1859
|
+
const status = error.status || error.statusCode || 500;
|
|
1860
|
+
if (status === 404 && defaultRes.status === 302) {
|
|
1861
|
+
setResponseHeaders(event, defaultRes.headers);
|
|
1862
|
+
setResponseStatus(event, defaultRes.status, defaultRes.statusText);
|
|
1863
|
+
return send(event, JSON.stringify(defaultRes.body, null, 2));
|
|
1864
|
+
}
|
|
1865
|
+
if (typeof defaultRes.body !== "string" && Array.isArray(defaultRes.body.stack)) {
|
|
1866
|
+
// normalize to string format expected by nuxt `error.vue`
|
|
1867
|
+
defaultRes.body.stack = defaultRes.body.stack.join("\n");
|
|
1868
|
+
}
|
|
1869
|
+
const errorObject = defaultRes.body;
|
|
1870
|
+
// remove proto/hostname/port from URL
|
|
1871
|
+
const url = new URL(errorObject.url);
|
|
1872
|
+
errorObject.url = withoutBase(url.pathname, useRuntimeConfig(event).app.baseURL) + url.search + url.hash;
|
|
1873
|
+
// add default server message (keep sanitized for unhandled errors)
|
|
1874
|
+
errorObject.message = error.unhandled ? errorObject.message || "Server Error" : error.message || errorObject.message || "Server Error";
|
|
1875
|
+
// we will be rendering this error internally so we can pass along the error.data safely
|
|
1876
|
+
errorObject.data ||= error.data;
|
|
1877
|
+
errorObject.statusText ||= error.statusText || error.statusMessage;
|
|
1878
|
+
delete defaultRes.headers["content-type"];
|
|
1879
|
+
delete defaultRes.headers["content-security-policy"];
|
|
1880
|
+
setResponseHeaders(event, defaultRes.headers);
|
|
1881
|
+
// Access request headers
|
|
1882
|
+
const reqHeaders = getRequestHeaders(event);
|
|
1883
|
+
// Detect to avoid recursion in SSR rendering of errors
|
|
1884
|
+
const isRenderingError = event.path.startsWith("/__nuxt_error") || !!reqHeaders["x-nuxt-error"];
|
|
1885
|
+
// HTML response (via SSR)
|
|
1886
|
+
const res = isRenderingError ? null : await useNitroApp().localFetch(withQuery(joinURL(useRuntimeConfig(event).app.baseURL, "/__nuxt_error"), errorObject), {
|
|
1887
|
+
headers: {
|
|
1888
|
+
...reqHeaders,
|
|
1889
|
+
"x-nuxt-error": "true"
|
|
1890
|
+
},
|
|
1891
|
+
redirect: "manual"
|
|
1892
|
+
}).catch(() => null);
|
|
1893
|
+
if (event.handled) {
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
// Fallback to static rendered error page
|
|
1897
|
+
if (!res) {
|
|
1898
|
+
const { template } = await Promise.resolve().then(function () { return error500; });
|
|
1899
|
+
{
|
|
1900
|
+
// TODO: Support `message` in template
|
|
1901
|
+
errorObject.description = errorObject.message;
|
|
1902
|
+
}
|
|
1903
|
+
setResponseHeader(event, "Content-Type", "text/html;charset=UTF-8");
|
|
1904
|
+
return send(event, template(errorObject));
|
|
1905
|
+
}
|
|
1906
|
+
const html = await res.text();
|
|
1907
|
+
for (const [header, value] of res.headers.entries()) {
|
|
1908
|
+
if (header === "set-cookie") {
|
|
1909
|
+
appendResponseHeader(event, header, value);
|
|
1910
|
+
continue;
|
|
1911
|
+
}
|
|
1912
|
+
setResponseHeader(event, header, value);
|
|
1913
|
+
}
|
|
1914
|
+
setResponseStatus(event, res.status && res.status !== 200 ? res.status : defaultRes.status, res.statusText || defaultRes.statusText);
|
|
1915
|
+
if (!globalThis._importMeta_.test && typeof html === "string") {
|
|
1916
|
+
const prettyResponse = await defaultHandler(error, event, { json: false });
|
|
1917
|
+
if (typeof prettyResponse.body === "string") {
|
|
1918
|
+
return send(event, html.replace("</body>", `${generateErrorOverlayHTML(prettyResponse.body, { startMinimized: 300 <= status && status < 500 })}</body>`));
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
return send(event, html);
|
|
1922
|
+
});
|
|
1923
|
+
|
|
1924
|
+
function defineNitroErrorHandler(handler) {
|
|
1925
|
+
return handler;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
const errorHandler$1 = defineNitroErrorHandler(
|
|
1929
|
+
async function defaultNitroErrorHandler(error, event) {
|
|
1930
|
+
const res = await defaultHandler(error, event);
|
|
1931
|
+
if (!event.node?.res.headersSent) {
|
|
1932
|
+
setResponseHeaders(event, res.headers);
|
|
1933
|
+
}
|
|
1934
|
+
setResponseStatus(event, res.status, res.statusText);
|
|
1935
|
+
return send(
|
|
1936
|
+
event,
|
|
1937
|
+
typeof res.body === "string" ? res.body : JSON.stringify(res.body, null, 2)
|
|
1938
|
+
);
|
|
1939
|
+
}
|
|
1940
|
+
);
|
|
1941
|
+
async function defaultHandler(error, event, opts) {
|
|
1942
|
+
const isSensitive = error.unhandled || error.fatal;
|
|
1943
|
+
const statusCode = error.statusCode || 500;
|
|
1944
|
+
const statusMessage = error.statusMessage || "Server Error";
|
|
1945
|
+
const url = getRequestURL(event, { xForwardedHost: true, xForwardedProto: true });
|
|
1946
|
+
if (statusCode === 404) {
|
|
1947
|
+
const baseURL = "/";
|
|
1948
|
+
if (/^\/[^/]/.test(baseURL) && !url.pathname.startsWith(baseURL)) {
|
|
1949
|
+
const redirectTo = `${baseURL}${url.pathname.slice(1)}${url.search}`;
|
|
1950
|
+
return {
|
|
1951
|
+
status: 302,
|
|
1952
|
+
statusText: "Found",
|
|
1953
|
+
headers: { location: redirectTo },
|
|
1954
|
+
body: `Redirecting...`
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
await loadStackTrace(error).catch(consola.error);
|
|
1959
|
+
const youch = new Youch();
|
|
1960
|
+
if (isSensitive && !opts?.silent) {
|
|
1961
|
+
const tags = [error.unhandled && "[unhandled]", error.fatal && "[fatal]"].filter(Boolean).join(" ");
|
|
1962
|
+
const ansiError = await (await youch.toANSI(error)).replaceAll(process.cwd(), ".");
|
|
1963
|
+
consola.error(
|
|
1964
|
+
`[request error] ${tags} [${event.method}] ${url}
|
|
1965
|
+
|
|
1966
|
+
`,
|
|
1967
|
+
ansiError
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
const useJSON = opts?.json ?? !getRequestHeader(event, "accept")?.includes("text/html");
|
|
1971
|
+
const headers = {
|
|
1972
|
+
"content-type": useJSON ? "application/json" : "text/html",
|
|
1973
|
+
// Prevent browser from guessing the MIME types of resources.
|
|
1974
|
+
"x-content-type-options": "nosniff",
|
|
1975
|
+
// Prevent error page from being embedded in an iframe
|
|
1976
|
+
"x-frame-options": "DENY",
|
|
1977
|
+
// Prevent browsers from sending the Referer header
|
|
1978
|
+
"referrer-policy": "no-referrer",
|
|
1979
|
+
// Disable the execution of any js
|
|
1980
|
+
"content-security-policy": "script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self';"
|
|
1981
|
+
};
|
|
1982
|
+
if (statusCode === 404 || !getResponseHeader(event, "cache-control")) {
|
|
1983
|
+
headers["cache-control"] = "no-cache";
|
|
1984
|
+
}
|
|
1985
|
+
const body = useJSON ? {
|
|
1986
|
+
error: true,
|
|
1987
|
+
url,
|
|
1988
|
+
statusCode,
|
|
1989
|
+
statusMessage,
|
|
1990
|
+
message: error.message,
|
|
1991
|
+
data: error.data,
|
|
1992
|
+
stack: error.stack?.split("\n").map((line) => line.trim())
|
|
1993
|
+
} : await youch.toHTML(error, {
|
|
1994
|
+
request: {
|
|
1995
|
+
url: url.href,
|
|
1996
|
+
method: event.method,
|
|
1997
|
+
headers: getRequestHeaders(event)
|
|
1998
|
+
}
|
|
1999
|
+
});
|
|
2000
|
+
return {
|
|
2001
|
+
status: statusCode,
|
|
2002
|
+
statusText: statusMessage,
|
|
2003
|
+
headers,
|
|
2004
|
+
body
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
async function loadStackTrace(error) {
|
|
2008
|
+
if (!(error instanceof Error)) {
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
const parsed = await new ErrorParser().defineSourceLoader(sourceLoader).parse(error);
|
|
2012
|
+
const stack = error.message + "\n" + parsed.frames.map((frame) => fmtFrame(frame)).join("\n");
|
|
2013
|
+
Object.defineProperty(error, "stack", { value: stack });
|
|
2014
|
+
if (error.cause) {
|
|
2015
|
+
await loadStackTrace(error.cause).catch(consola.error);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
async function sourceLoader(frame) {
|
|
2019
|
+
if (!frame.fileName || frame.fileType !== "fs" || frame.type === "native") {
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
if (frame.type === "app") {
|
|
2023
|
+
const rawSourceMap = await readFile(`${frame.fileName}.map`, "utf8").catch(() => {
|
|
2024
|
+
});
|
|
2025
|
+
if (rawSourceMap) {
|
|
2026
|
+
const consumer = await new SourceMapConsumer(rawSourceMap);
|
|
2027
|
+
const originalPosition = consumer.originalPositionFor({ line: frame.lineNumber, column: frame.columnNumber });
|
|
2028
|
+
if (originalPosition.source && originalPosition.line) {
|
|
2029
|
+
frame.fileName = resolve(dirname(frame.fileName), originalPosition.source);
|
|
2030
|
+
frame.lineNumber = originalPosition.line;
|
|
2031
|
+
frame.columnNumber = originalPosition.column || 0;
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
const contents = await readFile(frame.fileName, "utf8").catch(() => {
|
|
2036
|
+
});
|
|
2037
|
+
return contents ? { contents } : void 0;
|
|
2038
|
+
}
|
|
2039
|
+
function fmtFrame(frame) {
|
|
2040
|
+
if (frame.type === "native") {
|
|
2041
|
+
return frame.raw;
|
|
2042
|
+
}
|
|
2043
|
+
const src = `${frame.fileName || ""}:${frame.lineNumber}:${frame.columnNumber})`;
|
|
2044
|
+
return frame.functionName ? `at ${frame.functionName} (${src}` : `at ${src}`;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
const errorHandlers = [errorHandler$0, errorHandler$1];
|
|
2048
|
+
|
|
2049
|
+
async function errorHandler(error, event) {
|
|
2050
|
+
for (const handler of errorHandlers) {
|
|
2051
|
+
try {
|
|
2052
|
+
await handler(error, event, { defaultHandler });
|
|
2053
|
+
if (event.handled) {
|
|
2054
|
+
return; // Response handled
|
|
2055
|
+
}
|
|
2056
|
+
} catch(error) {
|
|
2057
|
+
// Handler itself thrown, log and continue
|
|
2058
|
+
console.error(error);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
// H3 will handle fallback
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
const script = `
|
|
2065
|
+
if (!window.__NUXT_DEVTOOLS_TIME_METRIC__) {
|
|
2066
|
+
Object.defineProperty(window, '__NUXT_DEVTOOLS_TIME_METRIC__', {
|
|
2067
|
+
value: {},
|
|
2068
|
+
enumerable: false,
|
|
2069
|
+
configurable: true,
|
|
2070
|
+
})
|
|
2071
|
+
}
|
|
2072
|
+
window.__NUXT_DEVTOOLS_TIME_METRIC__.appInit = Date.now()
|
|
2073
|
+
`;
|
|
2074
|
+
|
|
2075
|
+
const _S7DPrgXM_vAz0MUbsQr9zCWb8lLVJtyoOZQmBzOiis = (function(nitro) {
|
|
2076
|
+
nitro.hooks.hook("render:html", (htmlContext) => {
|
|
2077
|
+
htmlContext.head.push(`<script>${script}<\/script>`);
|
|
2078
|
+
});
|
|
2079
|
+
});
|
|
2080
|
+
|
|
2081
|
+
/*!
|
|
2082
|
+
* shared v11.2.8
|
|
2083
|
+
* (c) 2025 kazuya kawaguchi
|
|
2084
|
+
* Released under the MIT License.
|
|
2085
|
+
*/
|
|
2086
|
+
const _create = Object.create;
|
|
2087
|
+
const create = (obj = null) => _create(obj);
|
|
2088
|
+
/* eslint-enable */
|
|
2089
|
+
/**
|
|
2090
|
+
* Useful Utilities By Evan you
|
|
2091
|
+
* Modified by kazuya kawaguchi
|
|
2092
|
+
* MIT License
|
|
2093
|
+
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
|
|
2094
|
+
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
|
|
2095
|
+
*/
|
|
2096
|
+
const isArray = Array.isArray;
|
|
2097
|
+
const isFunction = (val) => typeof val === 'function';
|
|
2098
|
+
const isString = (val) => typeof val === 'string';
|
|
2099
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2100
|
+
const isObject = (val) => val !== null && typeof val === 'object';
|
|
2101
|
+
const objectToString = Object.prototype.toString;
|
|
2102
|
+
const toTypeString = (value) => objectToString.call(value);
|
|
2103
|
+
|
|
2104
|
+
const isNotObjectOrIsArray = (val) => !isObject(val) || isArray(val);
|
|
2105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2106
|
+
function deepCopy(src, des) {
|
|
2107
|
+
// src and des should both be objects, and none of them can be a array
|
|
2108
|
+
if (isNotObjectOrIsArray(src) || isNotObjectOrIsArray(des)) {
|
|
2109
|
+
throw new Error('Invalid value');
|
|
2110
|
+
}
|
|
2111
|
+
const stack = [{ src, des }];
|
|
2112
|
+
while (stack.length) {
|
|
2113
|
+
const { src, des } = stack.pop();
|
|
2114
|
+
// using `Object.keys` which skips prototype properties
|
|
2115
|
+
Object.keys(src).forEach(key => {
|
|
2116
|
+
if (key === '__proto__') {
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
2119
|
+
// if src[key] is an object/array, set des[key]
|
|
2120
|
+
// to empty object/array to prevent setting by reference
|
|
2121
|
+
if (isObject(src[key]) && !isObject(des[key])) {
|
|
2122
|
+
des[key] = Array.isArray(src[key]) ? [] : create();
|
|
2123
|
+
}
|
|
2124
|
+
if (isNotObjectOrIsArray(des[key]) || isNotObjectOrIsArray(src[key])) {
|
|
2125
|
+
// replace with src[key] when:
|
|
2126
|
+
// src[key] or des[key] is not an object, or
|
|
2127
|
+
// src[key] or des[key] is an array
|
|
2128
|
+
des[key] = src[key];
|
|
2129
|
+
}
|
|
2130
|
+
else {
|
|
2131
|
+
// src[key] and des[key] are both objects, merge them
|
|
2132
|
+
stack.push({ src: src[key], des: des[key] });
|
|
2133
|
+
}
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
const __nuxtMock = { runWithContext: async (fn) => await fn() };
|
|
2139
|
+
const merger = createDefu((obj, key, value) => {
|
|
2140
|
+
if (key === "messages" || key === "datetimeFormats" || key === "numberFormats") {
|
|
2141
|
+
obj[key] ??= create(null);
|
|
2142
|
+
deepCopy(value, obj[key]);
|
|
2143
|
+
return true;
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
async function loadVueI18nOptions(vueI18nConfigs) {
|
|
2147
|
+
const nuxtApp = __nuxtMock;
|
|
2148
|
+
let vueI18nOptions = { messages: create(null) };
|
|
2149
|
+
for (const configFile of vueI18nConfigs) {
|
|
2150
|
+
const resolver = await configFile().then((x) => isModule(x) ? x.default : x);
|
|
2151
|
+
const resolved = isFunction(resolver) ? await nuxtApp.runWithContext(() => resolver()) : resolver;
|
|
2152
|
+
vueI18nOptions = merger(create(null), resolved, vueI18nOptions);
|
|
2153
|
+
}
|
|
2154
|
+
vueI18nOptions.fallbackLocale ??= false;
|
|
2155
|
+
return vueI18nOptions;
|
|
2156
|
+
}
|
|
2157
|
+
const isModule = (val) => toTypeString(val) === "[object Module]";
|
|
2158
|
+
async function getLocaleMessages(locale, loader) {
|
|
2159
|
+
const nuxtApp = __nuxtMock;
|
|
2160
|
+
try {
|
|
2161
|
+
const getter = await nuxtApp.runWithContext(loader.load).then((x) => isModule(x) ? x.default : x);
|
|
2162
|
+
return isFunction(getter) ? await nuxtApp.runWithContext(() => getter(locale)) : getter;
|
|
2163
|
+
} catch (e) {
|
|
2164
|
+
throw new Error(`Failed loading locale (${locale}): ` + e.message);
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
async function getLocaleMessagesMerged(locale, loaders = []) {
|
|
2168
|
+
const nuxtApp = __nuxtMock;
|
|
2169
|
+
const messages = await Promise.all(
|
|
2170
|
+
loaders.map((loader) => nuxtApp.runWithContext(() => getLocaleMessages(locale, loader)))
|
|
2171
|
+
);
|
|
2172
|
+
const merged = {};
|
|
2173
|
+
for (const message of messages) {
|
|
2174
|
+
deepCopy(message, merged);
|
|
2175
|
+
}
|
|
2176
|
+
return merged;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
var common$1 = {
|
|
2180
|
+
loading: "加载编辑器...",
|
|
2181
|
+
generating: "生成工作流..."
|
|
2182
|
+
};
|
|
2183
|
+
var toolbar$1 = {
|
|
2184
|
+
draw: "绘制",
|
|
2185
|
+
shape: "图形",
|
|
2186
|
+
style: "样式",
|
|
2187
|
+
insert: "插入",
|
|
2188
|
+
save: "保存",
|
|
2189
|
+
"import": "导入",
|
|
2190
|
+
undo: "撤销",
|
|
2191
|
+
redo: "重做",
|
|
2192
|
+
zoomOut: "缩小",
|
|
2193
|
+
zoomIn: "放大",
|
|
2194
|
+
fitView: "适应视图",
|
|
2195
|
+
untitled: "未命名工作流"
|
|
2196
|
+
};
|
|
2197
|
+
var nodePanel$1 = {
|
|
2198
|
+
search: "搜索图形...",
|
|
2199
|
+
general: "通用",
|
|
2200
|
+
sysml: "SysML",
|
|
2201
|
+
advanced: "高级",
|
|
2202
|
+
moreShapes: "更多图形",
|
|
2203
|
+
noAdvanced: "暂无高级图形",
|
|
2204
|
+
nodes: {
|
|
2205
|
+
ai: "AI",
|
|
2206
|
+
aiFull: "AI 节点",
|
|
2207
|
+
action: "动作",
|
|
2208
|
+
actionFull: "动作节点",
|
|
2209
|
+
square: "正方形",
|
|
2210
|
+
circle: "圆形",
|
|
2211
|
+
diamond: "菱形",
|
|
2212
|
+
triangle: "三角形",
|
|
2213
|
+
cylinder: "圆柱体",
|
|
2214
|
+
file: "文件",
|
|
2215
|
+
sysmlBlock: "SysML 块",
|
|
2216
|
+
sysmlReq: "需求",
|
|
2217
|
+
sysmlUseCase: "用例",
|
|
2218
|
+
sysmlBlockFull: "SysML 块定义",
|
|
2219
|
+
sysmlReqFull: "SysML 需求",
|
|
2220
|
+
sysmlUseCaseFull: "SysML 用例"
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
var aiChat$1 = {
|
|
2224
|
+
title: "AI 助手",
|
|
2225
|
+
"new": "新",
|
|
2226
|
+
v2: "工作流生成 V2",
|
|
2227
|
+
desc: "自然语言描述业务逻辑,支持复杂分支和错误处理。",
|
|
2228
|
+
createTitle: "AI 创建",
|
|
2229
|
+
createDesc: "描述您想构建的工作流,或上传图片进行复刻。",
|
|
2230
|
+
quickStarts: "快速开始",
|
|
2231
|
+
docProcess: {
|
|
2232
|
+
title: "文档处理",
|
|
2233
|
+
desc: "自动解析 PDF/JSON 文件"
|
|
2234
|
+
},
|
|
2235
|
+
userAuth: {
|
|
2236
|
+
title: "用户认证",
|
|
2237
|
+
desc: "注册与验证流程"
|
|
2238
|
+
},
|
|
2239
|
+
etl: {
|
|
2240
|
+
title: "ETL 管道",
|
|
2241
|
+
desc: "提取、转换、加载数据"
|
|
2242
|
+
},
|
|
2243
|
+
inputPlaceholder: "描述您的工作流...",
|
|
2244
|
+
generate: "生成",
|
|
2245
|
+
quickInputs: {
|
|
2246
|
+
doc: "创建一个文档处理工作流",
|
|
2247
|
+
auth: "创建一个带有邮箱验证的用户注册流程",
|
|
2248
|
+
etl: "创建一个数据 ETL 管道"
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
var aiGenerator$1 = {
|
|
2252
|
+
title: "AI 生成工作流",
|
|
2253
|
+
placeholder: "在此描述您的工作流逻辑...",
|
|
2254
|
+
cancel: "取消",
|
|
2255
|
+
generate: "生成"
|
|
2256
|
+
};
|
|
2257
|
+
var propertyPanel$1 = {
|
|
2258
|
+
title: "格式",
|
|
2259
|
+
noSelection: "未选中节点",
|
|
2260
|
+
tabs: {
|
|
2261
|
+
style: "样式",
|
|
2262
|
+
text: "文本",
|
|
2263
|
+
arrange: "调整图形"
|
|
2264
|
+
},
|
|
2265
|
+
style: {
|
|
2266
|
+
fill: "填充",
|
|
2267
|
+
stroke: "线条",
|
|
2268
|
+
opacity: "不透明度",
|
|
2269
|
+
rounded: "圆角",
|
|
2270
|
+
shadow: "阴影"
|
|
2271
|
+
},
|
|
2272
|
+
text: {
|
|
2273
|
+
content: "内容",
|
|
2274
|
+
color: "字体颜色"
|
|
2275
|
+
},
|
|
2276
|
+
arrange: {
|
|
2277
|
+
front: "移至最前",
|
|
2278
|
+
back: "移至最后",
|
|
2279
|
+
size: "大小",
|
|
2280
|
+
position: "位置"
|
|
2281
|
+
}
|
|
2282
|
+
};
|
|
2283
|
+
const locale_zh_46json_8308e862 = {
|
|
2284
|
+
common: common$1,
|
|
2285
|
+
toolbar: toolbar$1,
|
|
2286
|
+
nodePanel: nodePanel$1,
|
|
2287
|
+
aiChat: aiChat$1,
|
|
2288
|
+
aiGenerator: aiGenerator$1,
|
|
2289
|
+
propertyPanel: propertyPanel$1
|
|
2290
|
+
};
|
|
2291
|
+
|
|
2292
|
+
var common = {
|
|
2293
|
+
loading: "Loading Editor...",
|
|
2294
|
+
generating: "Generating Workflow..."
|
|
2295
|
+
};
|
|
2296
|
+
var toolbar = {
|
|
2297
|
+
draw: "Draw",
|
|
2298
|
+
shape: "Shape",
|
|
2299
|
+
style: "Style",
|
|
2300
|
+
insert: "Insert",
|
|
2301
|
+
save: "Save",
|
|
2302
|
+
"import": "Import",
|
|
2303
|
+
undo: "Undo",
|
|
2304
|
+
redo: "Redo",
|
|
2305
|
+
zoomOut: "Zoom Out",
|
|
2306
|
+
zoomIn: "Zoom In",
|
|
2307
|
+
fitView: "Fit View",
|
|
2308
|
+
untitled: "Untitled Workflow"
|
|
2309
|
+
};
|
|
2310
|
+
var nodePanel = {
|
|
2311
|
+
search: "Search shapes...",
|
|
2312
|
+
general: "General",
|
|
2313
|
+
sysml: "SysML",
|
|
2314
|
+
advanced: "Advanced",
|
|
2315
|
+
moreShapes: "More Shapes",
|
|
2316
|
+
noAdvanced: "No advanced shapes yet",
|
|
2317
|
+
nodes: {
|
|
2318
|
+
ai: "AI",
|
|
2319
|
+
aiFull: "AI Node",
|
|
2320
|
+
action: "Action",
|
|
2321
|
+
actionFull: "Action Node",
|
|
2322
|
+
square: "Square",
|
|
2323
|
+
circle: "Circle",
|
|
2324
|
+
diamond: "Diamond",
|
|
2325
|
+
triangle: "Triangle",
|
|
2326
|
+
cylinder: "Cylinder",
|
|
2327
|
+
file: "File",
|
|
2328
|
+
sysmlBlock: "Block",
|
|
2329
|
+
sysmlReq: "Requirement",
|
|
2330
|
+
sysmlUseCase: "Use Case",
|
|
2331
|
+
sysmlBlockFull: "SysML Block",
|
|
2332
|
+
sysmlReqFull: "SysML Requirement",
|
|
2333
|
+
sysmlUseCaseFull: "SysML Use Case"
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
var aiChat = {
|
|
2337
|
+
title: "AI Assistant",
|
|
2338
|
+
"new": "NEW",
|
|
2339
|
+
v2: "Workflow Gen V2",
|
|
2340
|
+
desc: "Describe your business logic naturally. Supports complex branching and error handling.",
|
|
2341
|
+
createTitle: "Create with AI",
|
|
2342
|
+
createDesc: "Describe the workflow you want to build or upload an image to replicate.",
|
|
2343
|
+
quickStarts: "Quick Starts",
|
|
2344
|
+
docProcess: {
|
|
2345
|
+
title: "Doc Processing",
|
|
2346
|
+
desc: "Parse PDF/JSON files automatically"
|
|
2347
|
+
},
|
|
2348
|
+
userAuth: {
|
|
2349
|
+
title: "User Auth",
|
|
2350
|
+
desc: "Registration & Verification flow"
|
|
2351
|
+
},
|
|
2352
|
+
etl: {
|
|
2353
|
+
title: "ETL Pipeline",
|
|
2354
|
+
desc: "Extract, Transform, Load data"
|
|
2355
|
+
},
|
|
2356
|
+
inputPlaceholder: "Describe your workflow...",
|
|
2357
|
+
generate: "Generate",
|
|
2358
|
+
quickInputs: {
|
|
2359
|
+
doc: "Create a document processing workflow",
|
|
2360
|
+
auth: "Create a user registration flow with email verification",
|
|
2361
|
+
etl: "Create a data ETL pipeline"
|
|
2362
|
+
}
|
|
2363
|
+
};
|
|
2364
|
+
var aiGenerator = {
|
|
2365
|
+
title: "Generate Workflow with AI",
|
|
2366
|
+
placeholder: "Describe your workflow logic here...",
|
|
2367
|
+
cancel: "Cancel",
|
|
2368
|
+
generate: "Generate"
|
|
2369
|
+
};
|
|
2370
|
+
var propertyPanel = {
|
|
2371
|
+
title: "Format",
|
|
2372
|
+
noSelection: "No Selection",
|
|
2373
|
+
tabs: {
|
|
2374
|
+
style: "Style",
|
|
2375
|
+
text: "Text",
|
|
2376
|
+
arrange: "Arrange"
|
|
2377
|
+
},
|
|
2378
|
+
style: {
|
|
2379
|
+
fill: "Fill",
|
|
2380
|
+
stroke: "Stroke",
|
|
2381
|
+
opacity: "Opacity",
|
|
2382
|
+
rounded: "Rounded",
|
|
2383
|
+
shadow: "Shadow"
|
|
2384
|
+
},
|
|
2385
|
+
text: {
|
|
2386
|
+
content: "Content",
|
|
2387
|
+
color: "Text Color"
|
|
2388
|
+
},
|
|
2389
|
+
arrange: {
|
|
2390
|
+
front: "Bring to Front",
|
|
2391
|
+
back: "Send to Back",
|
|
2392
|
+
size: "Size",
|
|
2393
|
+
position: "Position"
|
|
2394
|
+
}
|
|
2395
|
+
};
|
|
2396
|
+
const locale_en_46json_a37002f9 = {
|
|
2397
|
+
common: common,
|
|
2398
|
+
toolbar: toolbar,
|
|
2399
|
+
nodePanel: nodePanel,
|
|
2400
|
+
aiChat: aiChat,
|
|
2401
|
+
aiGenerator: aiGenerator,
|
|
2402
|
+
propertyPanel: propertyPanel
|
|
2403
|
+
};
|
|
2404
|
+
|
|
2405
|
+
// @ts-nocheck
|
|
2406
|
+
const localeCodes = [
|
|
2407
|
+
"zh",
|
|
2408
|
+
"en"
|
|
2409
|
+
];
|
|
2410
|
+
const localeLoaders = {
|
|
2411
|
+
zh: [
|
|
2412
|
+
{
|
|
2413
|
+
key: "locale_zh_46json_8308e862",
|
|
2414
|
+
load: () => Promise.resolve(locale_zh_46json_8308e862),
|
|
2415
|
+
cache: true
|
|
2416
|
+
}
|
|
2417
|
+
],
|
|
2418
|
+
en: [
|
|
2419
|
+
{
|
|
2420
|
+
key: "locale_en_46json_a37002f9",
|
|
2421
|
+
load: () => Promise.resolve(locale_en_46json_a37002f9),
|
|
2422
|
+
cache: true
|
|
2423
|
+
}
|
|
2424
|
+
]
|
|
2425
|
+
};
|
|
2426
|
+
const vueI18nConfigs = [];
|
|
2427
|
+
const normalizedLocales = [
|
|
2428
|
+
{
|
|
2429
|
+
code: "zh",
|
|
2430
|
+
name: "中文",
|
|
2431
|
+
language: undefined
|
|
2432
|
+
},
|
|
2433
|
+
{
|
|
2434
|
+
code: "en",
|
|
2435
|
+
name: "English",
|
|
2436
|
+
language: undefined
|
|
2437
|
+
}
|
|
2438
|
+
];
|
|
2439
|
+
|
|
2440
|
+
const setupVueI18nOptions = async (defaultLocale) => {
|
|
2441
|
+
const options = await loadVueI18nOptions(vueI18nConfigs);
|
|
2442
|
+
options.locale = defaultLocale || options.locale || "en-US";
|
|
2443
|
+
options.defaultLocale = defaultLocale;
|
|
2444
|
+
options.fallbackLocale ??= false;
|
|
2445
|
+
options.messages ??= {};
|
|
2446
|
+
for (const locale of localeCodes) {
|
|
2447
|
+
options.messages[locale] ??= {};
|
|
2448
|
+
}
|
|
2449
|
+
return options;
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2452
|
+
function defineNitroPlugin(def) {
|
|
2453
|
+
return def;
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
function defineRenderHandler(render) {
|
|
2457
|
+
const runtimeConfig = useRuntimeConfig();
|
|
2458
|
+
return eventHandler(async (event) => {
|
|
2459
|
+
const nitroApp = useNitroApp();
|
|
2460
|
+
const ctx = { event, render, response: void 0 };
|
|
2461
|
+
await nitroApp.hooks.callHook("render:before", ctx);
|
|
2462
|
+
if (!ctx.response) {
|
|
2463
|
+
if (event.path === `${runtimeConfig.app.baseURL}favicon.ico`) {
|
|
2464
|
+
setResponseHeader(event, "Content-Type", "image/x-icon");
|
|
2465
|
+
return send(
|
|
2466
|
+
event,
|
|
2467
|
+
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2470
|
+
ctx.response = await ctx.render(event);
|
|
2471
|
+
if (!ctx.response) {
|
|
2472
|
+
const _currentStatus = getResponseStatus(event);
|
|
2473
|
+
setResponseStatus(event, _currentStatus === 200 ? 500 : _currentStatus);
|
|
2474
|
+
return send(
|
|
2475
|
+
event,
|
|
2476
|
+
"No response returned from render handler: " + event.path
|
|
2477
|
+
);
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
await nitroApp.hooks.callHook("render:response", ctx.response, ctx);
|
|
2481
|
+
if (ctx.response.headers) {
|
|
2482
|
+
setResponseHeaders(event, ctx.response.headers);
|
|
2483
|
+
}
|
|
2484
|
+
if (ctx.response.statusCode || ctx.response.statusMessage) {
|
|
2485
|
+
setResponseStatus(
|
|
2486
|
+
event,
|
|
2487
|
+
ctx.response.statusCode,
|
|
2488
|
+
ctx.response.statusMessage
|
|
2489
|
+
);
|
|
2490
|
+
}
|
|
2491
|
+
return ctx.response.body;
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
const scheduledTasks = false;
|
|
2496
|
+
|
|
2497
|
+
const tasks = {
|
|
2498
|
+
|
|
2499
|
+
};
|
|
2500
|
+
|
|
2501
|
+
const __runningTasks__ = {};
|
|
2502
|
+
async function runTask(name, {
|
|
2503
|
+
payload = {},
|
|
2504
|
+
context = {}
|
|
2505
|
+
} = {}) {
|
|
2506
|
+
if (__runningTasks__[name]) {
|
|
2507
|
+
return __runningTasks__[name];
|
|
2508
|
+
}
|
|
2509
|
+
if (!(name in tasks)) {
|
|
2510
|
+
throw createError({
|
|
2511
|
+
message: `Task \`${name}\` is not available!`,
|
|
2512
|
+
statusCode: 404
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
if (!tasks[name].resolve) {
|
|
2516
|
+
throw createError({
|
|
2517
|
+
message: `Task \`${name}\` is not implemented!`,
|
|
2518
|
+
statusCode: 501
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
const handler = await tasks[name].resolve();
|
|
2522
|
+
const taskEvent = { name, payload, context };
|
|
2523
|
+
__runningTasks__[name] = handler.run(taskEvent);
|
|
2524
|
+
try {
|
|
2525
|
+
const res = await __runningTasks__[name];
|
|
2526
|
+
return res;
|
|
2527
|
+
} finally {
|
|
2528
|
+
delete __runningTasks__[name];
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
function buildAssetsDir() {
|
|
2533
|
+
// TODO: support passing event to `useRuntimeConfig`
|
|
2534
|
+
return useRuntimeConfig().app.buildAssetsDir;
|
|
2535
|
+
}
|
|
2536
|
+
function buildAssetsURL(...path) {
|
|
2537
|
+
return joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path);
|
|
2538
|
+
}
|
|
2539
|
+
function publicAssetsURL(...path) {
|
|
2540
|
+
// TODO: support passing event to `useRuntimeConfig`
|
|
2541
|
+
const app = useRuntimeConfig().app;
|
|
2542
|
+
const publicBase = app.cdnURL || app.baseURL;
|
|
2543
|
+
return path.length ? joinRelativeURL(publicBase, ...path) : publicBase;
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
function parseAcceptLanguage(value) {
|
|
2547
|
+
return value.split(",").map((tag) => tag.split(";")[0]).filter(
|
|
2548
|
+
(tag) => !(tag === "*" || tag === "")
|
|
2549
|
+
);
|
|
2550
|
+
}
|
|
2551
|
+
function createPathIndexLanguageParser(index = 0) {
|
|
2552
|
+
return (path) => {
|
|
2553
|
+
const rawPath = typeof path === "string" ? path : path.pathname;
|
|
2554
|
+
const normalizedPath = rawPath.split("?")[0];
|
|
2555
|
+
const parts = normalizedPath.split("/");
|
|
2556
|
+
if (parts[0] === "") {
|
|
2557
|
+
parts.shift();
|
|
2558
|
+
}
|
|
2559
|
+
return parts.length > index ? parts[index] || "" : "";
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
function useRuntimeI18n(nuxtApp, event) {
|
|
2564
|
+
{
|
|
2565
|
+
return useRuntimeConfig(event).public.i18n;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
function useI18nDetection(nuxtApp) {
|
|
2569
|
+
const detectBrowserLanguage = useRuntimeI18n().detectBrowserLanguage;
|
|
2570
|
+
const detect = detectBrowserLanguage || {};
|
|
2571
|
+
return {
|
|
2572
|
+
...detect,
|
|
2573
|
+
enabled: !!detectBrowserLanguage,
|
|
2574
|
+
cookieKey: detect.cookieKey || "i18n_redirected"
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
function resolveRootRedirect(config) {
|
|
2578
|
+
if (!config) {
|
|
2579
|
+
return void 0;
|
|
2580
|
+
}
|
|
2581
|
+
return {
|
|
2582
|
+
path: "/" + (isString(config) ? config : config.path).replace(/^\//, ""),
|
|
2583
|
+
code: !isString(config) && config.statusCode || 302
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
function toArray(value) {
|
|
2587
|
+
return Array.isArray(value) ? value : [value];
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
function createLocaleConfigs(fallbackLocale) {
|
|
2591
|
+
const localeConfigs = {};
|
|
2592
|
+
for (const locale of localeCodes) {
|
|
2593
|
+
const fallbacks = getFallbackLocaleCodes(fallbackLocale, [locale]);
|
|
2594
|
+
const cacheable = isLocaleWithFallbacksCacheable(locale, fallbacks);
|
|
2595
|
+
localeConfigs[locale] = { fallbacks, cacheable };
|
|
2596
|
+
}
|
|
2597
|
+
return localeConfigs;
|
|
2598
|
+
}
|
|
2599
|
+
function getFallbackLocaleCodes(fallback, locales) {
|
|
2600
|
+
if (fallback === false) {
|
|
2601
|
+
return [];
|
|
2602
|
+
}
|
|
2603
|
+
if (isArray(fallback)) {
|
|
2604
|
+
return fallback;
|
|
2605
|
+
}
|
|
2606
|
+
let fallbackLocales = [];
|
|
2607
|
+
if (isString(fallback)) {
|
|
2608
|
+
if (locales.every((locale) => locale !== fallback)) {
|
|
2609
|
+
fallbackLocales.push(fallback);
|
|
2610
|
+
}
|
|
2611
|
+
return fallbackLocales;
|
|
2612
|
+
}
|
|
2613
|
+
const targets = [...locales, "default"];
|
|
2614
|
+
for (const locale of targets) {
|
|
2615
|
+
if (locale in fallback == false) {
|
|
2616
|
+
continue;
|
|
2617
|
+
}
|
|
2618
|
+
fallbackLocales = [...fallbackLocales, ...fallback[locale].filter(Boolean)];
|
|
2619
|
+
}
|
|
2620
|
+
return fallbackLocales;
|
|
2621
|
+
}
|
|
2622
|
+
function isLocaleCacheable(locale) {
|
|
2623
|
+
return localeLoaders[locale] != null && localeLoaders[locale].every((loader) => loader.cache !== false);
|
|
2624
|
+
}
|
|
2625
|
+
function isLocaleWithFallbacksCacheable(locale, fallbackLocales) {
|
|
2626
|
+
return isLocaleCacheable(locale) && fallbackLocales.every((fallbackLocale) => isLocaleCacheable(fallbackLocale));
|
|
2627
|
+
}
|
|
2628
|
+
function getDefaultLocaleForDomain(host) {
|
|
2629
|
+
return normalizedLocales.find((l) => !!l.defaultForDomains?.includes(host))?.code;
|
|
2630
|
+
}
|
|
2631
|
+
const isSupportedLocale = (locale) => localeCodes.includes(locale || "");
|
|
2632
|
+
|
|
2633
|
+
function useI18nContext(event) {
|
|
2634
|
+
if (event.context.nuxtI18n == null) {
|
|
2635
|
+
throw new Error("Nuxt I18n server context has not been set up yet.");
|
|
2636
|
+
}
|
|
2637
|
+
return event.context.nuxtI18n;
|
|
2638
|
+
}
|
|
2639
|
+
function tryUseI18nContext(event) {
|
|
2640
|
+
return event.context.nuxtI18n;
|
|
2641
|
+
}
|
|
2642
|
+
const getHost = (event) => getRequestURL(event, { xForwardedHost: true }).host;
|
|
2643
|
+
async function initializeI18nContext(event) {
|
|
2644
|
+
const runtimeI18n = useRuntimeI18n(void 0, event);
|
|
2645
|
+
const defaultLocale = runtimeI18n.defaultLocale || "";
|
|
2646
|
+
const options = await setupVueI18nOptions(getDefaultLocaleForDomain(getHost(event)) || defaultLocale);
|
|
2647
|
+
const localeConfigs = createLocaleConfigs(options.fallbackLocale);
|
|
2648
|
+
const ctx = createI18nContext();
|
|
2649
|
+
ctx.vueI18nOptions = options;
|
|
2650
|
+
ctx.localeConfigs = localeConfigs;
|
|
2651
|
+
event.context.nuxtI18n = ctx;
|
|
2652
|
+
return ctx;
|
|
2653
|
+
}
|
|
2654
|
+
function createI18nContext() {
|
|
2655
|
+
return {
|
|
2656
|
+
messages: {},
|
|
2657
|
+
slp: {},
|
|
2658
|
+
localeConfigs: {},
|
|
2659
|
+
trackMap: {},
|
|
2660
|
+
vueI18nOptions: void 0,
|
|
2661
|
+
trackKey(key, locale) {
|
|
2662
|
+
this.trackMap[locale] ??= /* @__PURE__ */ new Set();
|
|
2663
|
+
this.trackMap[locale].add(key);
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
function matchBrowserLocale(locales, browserLocales) {
|
|
2669
|
+
const matchedLocales = [];
|
|
2670
|
+
for (const [index, browserCode] of browserLocales.entries()) {
|
|
2671
|
+
const matchedLocale = locales.find((l) => l.language?.toLowerCase() === browserCode.toLowerCase());
|
|
2672
|
+
if (matchedLocale) {
|
|
2673
|
+
matchedLocales.push({ code: matchedLocale.code, score: 1 - index / browserLocales.length });
|
|
2674
|
+
break;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
for (const [index, browserCode] of browserLocales.entries()) {
|
|
2678
|
+
const languageCode = browserCode.split("-")[0].toLowerCase();
|
|
2679
|
+
const matchedLocale = locales.find((l) => l.language?.split("-")[0].toLowerCase() === languageCode);
|
|
2680
|
+
if (matchedLocale) {
|
|
2681
|
+
matchedLocales.push({ code: matchedLocale.code, score: 0.999 - index / browserLocales.length });
|
|
2682
|
+
break;
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
return matchedLocales;
|
|
2686
|
+
}
|
|
2687
|
+
function compareBrowserLocale(a, b) {
|
|
2688
|
+
if (a.score === b.score) {
|
|
2689
|
+
return b.code.length - a.code.length;
|
|
2690
|
+
}
|
|
2691
|
+
return b.score - a.score;
|
|
2692
|
+
}
|
|
2693
|
+
function findBrowserLocale(locales, browserLocales) {
|
|
2694
|
+
const matchedLocales = matchBrowserLocale(
|
|
2695
|
+
locales.map((l) => ({ code: l.code, language: l.language || l.code })),
|
|
2696
|
+
browserLocales
|
|
2697
|
+
);
|
|
2698
|
+
return matchedLocales.sort(compareBrowserLocale).at(0)?.code ?? "";
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
const appHead = {"meta":[{"name":"viewport","content":"width=device-width, initial-scale=1"},{"charset":"utf-8"}],"link":[],"style":[],"script":[],"noscript":[]};
|
|
2702
|
+
|
|
2703
|
+
const appRootTag = "div";
|
|
2704
|
+
|
|
2705
|
+
const appRootAttrs = {"id":"__nuxt"};
|
|
2706
|
+
|
|
2707
|
+
const appTeleportTag = "div";
|
|
2708
|
+
|
|
2709
|
+
const appTeleportAttrs = {"id":"teleports"};
|
|
2710
|
+
|
|
2711
|
+
const appId = "nuxt-app";
|
|
2712
|
+
|
|
2713
|
+
const separator = "___";
|
|
2714
|
+
const pathLanguageParser = createPathIndexLanguageParser(0);
|
|
2715
|
+
const getLocaleFromRoutePath = (path) => pathLanguageParser(path);
|
|
2716
|
+
const getLocaleFromRouteName = (name) => name.split(separator).at(1) ?? "";
|
|
2717
|
+
function normalizeInput(input) {
|
|
2718
|
+
return typeof input !== "object" ? String(input) : String(input?.name || input?.path || "");
|
|
2719
|
+
}
|
|
2720
|
+
function getLocaleFromRoute(route) {
|
|
2721
|
+
const input = normalizeInput(route);
|
|
2722
|
+
return input[0] === "/" ? getLocaleFromRoutePath(input) : getLocaleFromRouteName(input);
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
function matchDomainLocale(locales, host, pathLocale) {
|
|
2726
|
+
const normalizeDomain = (domain = "") => domain.replace(/https?:\/\//, "");
|
|
2727
|
+
const matches = locales.filter(
|
|
2728
|
+
(locale) => normalizeDomain(locale.domain) === host || toArray(locale.domains).includes(host)
|
|
2729
|
+
);
|
|
2730
|
+
if (matches.length <= 1) {
|
|
2731
|
+
return matches[0]?.code;
|
|
2732
|
+
}
|
|
2733
|
+
return (
|
|
2734
|
+
// match by current path locale
|
|
2735
|
+
matches.find((l) => l.code === pathLocale)?.code || matches.find((l) => l.defaultForDomains?.includes(host) ?? l.domainDefault)?.code
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
const getCookieLocale = (event, cookieName) => (getCookie(event, cookieName)) || void 0;
|
|
2740
|
+
const getRouteLocale = (event, route) => getLocaleFromRoute(route);
|
|
2741
|
+
const getHeaderLocale = (event) => findBrowserLocale(normalizedLocales, parseAcceptLanguage(getRequestHeader(event, "accept-language") || ""));
|
|
2742
|
+
const getHostLocale = (event, path, domainLocales) => {
|
|
2743
|
+
const host = getRequestURL(event, { xForwardedHost: true }).host;
|
|
2744
|
+
const locales = normalizedLocales.map((l) => ({
|
|
2745
|
+
...l,
|
|
2746
|
+
domain: domainLocales[l.code]?.domain ?? l.domain
|
|
2747
|
+
}));
|
|
2748
|
+
return matchDomainLocale(locales, host, getLocaleFromRoutePath(path));
|
|
2749
|
+
};
|
|
2750
|
+
const useDetectors = (event, config, nuxtApp) => {
|
|
2751
|
+
if (!event) {
|
|
2752
|
+
throw new Error("H3Event is required for server-side locale detection");
|
|
2753
|
+
}
|
|
2754
|
+
const runtimeI18n = useRuntimeI18n();
|
|
2755
|
+
return {
|
|
2756
|
+
cookie: () => getCookieLocale(event, config.cookieKey),
|
|
2757
|
+
header: () => getHeaderLocale(event) ,
|
|
2758
|
+
navigator: () => void 0,
|
|
2759
|
+
host: (path) => getHostLocale(event, path, runtimeI18n.domainLocales),
|
|
2760
|
+
route: (path) => getRouteLocale(event, path)
|
|
2761
|
+
};
|
|
2762
|
+
};
|
|
2763
|
+
|
|
2764
|
+
// Generated by @nuxtjs/i18n
|
|
2765
|
+
const pathToI18nConfig = {};
|
|
2766
|
+
const i18nPathToPath = {};
|
|
2767
|
+
|
|
2768
|
+
const matcher = createRouterMatcher([], {});
|
|
2769
|
+
for (const path of Object.keys(i18nPathToPath)) {
|
|
2770
|
+
matcher.addRoute({ path, component: () => "", meta: {} });
|
|
2771
|
+
}
|
|
2772
|
+
const getI18nPathToI18nPath = (path, locale) => {
|
|
2773
|
+
if (!path || !locale) {
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
const plainPath = i18nPathToPath[path];
|
|
2777
|
+
const i18nConfig = pathToI18nConfig[plainPath];
|
|
2778
|
+
if (i18nConfig && i18nConfig[locale]) {
|
|
2779
|
+
return i18nConfig[locale] === true ? plainPath : i18nConfig[locale];
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
function isExistingNuxtRoute(path) {
|
|
2783
|
+
if (path === "") {
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
if (path.endsWith("/__nuxt_error")) {
|
|
2787
|
+
return;
|
|
2788
|
+
}
|
|
2789
|
+
const resolvedMatch = matcher.resolve({ path }, { path: "/", name: "", matched: [], params: {}, meta: {} });
|
|
2790
|
+
return resolvedMatch.matched.length > 0 ? resolvedMatch : void 0;
|
|
2791
|
+
}
|
|
2792
|
+
function matchLocalized(path, locale, defaultLocale) {
|
|
2793
|
+
if (path === "") {
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
const parsed = parsePath(path);
|
|
2797
|
+
const resolvedMatch = matcher.resolve(
|
|
2798
|
+
{ path: parsed.pathname || "/" },
|
|
2799
|
+
{ path: "/", name: "", matched: [], params: {}, meta: {} }
|
|
2800
|
+
);
|
|
2801
|
+
if (resolvedMatch.matched.length > 0) {
|
|
2802
|
+
const alternate = getI18nPathToI18nPath(resolvedMatch.matched[0].path, locale);
|
|
2803
|
+
const match = matcher.resolve(
|
|
2804
|
+
{ params: resolvedMatch.params },
|
|
2805
|
+
{ path: alternate || "/", name: "", matched: [], params: {}, meta: {} }
|
|
2806
|
+
);
|
|
2807
|
+
return withLeadingSlash(joinURL("", match.path));
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
function* detect(detectors, detection, path) {
|
|
2812
|
+
if (detection.enabled) {
|
|
2813
|
+
yield { locale: detectors.cookie(), source: "cookie" };
|
|
2814
|
+
yield { locale: detectors.header(), source: "header" };
|
|
2815
|
+
}
|
|
2816
|
+
yield { locale: detection.fallbackLocale, source: "fallback" };
|
|
2817
|
+
}
|
|
2818
|
+
function createRedirectResponse(event, dest, code) {
|
|
2819
|
+
event.node.res.setHeader("location", dest);
|
|
2820
|
+
event.node.res.statusCode = sanitizeStatusCode(code, event.node.res.statusCode);
|
|
2821
|
+
return {
|
|
2822
|
+
headers: event.node.res.getHeaders(),
|
|
2823
|
+
statusCode: event.node.res.statusCode,
|
|
2824
|
+
body: `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${dest.replace(/"/g, "%22")}"></head></html>`
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
const _zJuKdirGFqxT2wiHdNbvYxI2qOaimipFm38nCQMg4Y = defineNitroPlugin(async (nitro) => {
|
|
2828
|
+
const runtimeI18n = useRuntimeI18n();
|
|
2829
|
+
const rootRedirect = resolveRootRedirect(runtimeI18n.rootRedirect);
|
|
2830
|
+
runtimeI18n.defaultLocale || "";
|
|
2831
|
+
try {
|
|
2832
|
+
const cacheStorage = useStorage("cache");
|
|
2833
|
+
const cachedKeys = await cacheStorage.getKeys("nitro:handlers:i18n");
|
|
2834
|
+
await Promise.all(cachedKeys.map((key) => cacheStorage.removeItem(key)));
|
|
2835
|
+
} catch {
|
|
2836
|
+
}
|
|
2837
|
+
const detection = useI18nDetection();
|
|
2838
|
+
const cookieOptions = {
|
|
2839
|
+
path: "/",
|
|
2840
|
+
domain: detection.cookieDomain || void 0,
|
|
2841
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
2842
|
+
sameSite: "lax",
|
|
2843
|
+
secure: detection.cookieSecure
|
|
2844
|
+
};
|
|
2845
|
+
const createBaseUrlGetter = () => {
|
|
2846
|
+
isFunction(runtimeI18n.baseUrl) ? "" : runtimeI18n.baseUrl || "";
|
|
2847
|
+
if (isFunction(runtimeI18n.baseUrl)) {
|
|
2848
|
+
console.warn("[nuxt-i18n] Configuring baseUrl as a function is deprecated and will be removed in v11.");
|
|
2849
|
+
return () => "";
|
|
2850
|
+
}
|
|
2851
|
+
return (event, defaultLocale) => {
|
|
2852
|
+
return "";
|
|
2853
|
+
};
|
|
2854
|
+
};
|
|
2855
|
+
function resolveRedirectPath(event, path, pathLocale, defaultLocale, detector) {
|
|
2856
|
+
let locale = "";
|
|
2857
|
+
for (const detected of detect(detector, detection, event.path)) {
|
|
2858
|
+
if (detected.locale && isSupportedLocale(detected.locale)) {
|
|
2859
|
+
locale = detected.locale;
|
|
2860
|
+
break;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
locale ||= defaultLocale;
|
|
2864
|
+
function getLocalizedMatch(locale2) {
|
|
2865
|
+
const res = matchLocalized(path || "/", locale2);
|
|
2866
|
+
if (res && res !== event.path) {
|
|
2867
|
+
return res;
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
let resolvedPath = void 0;
|
|
2871
|
+
let redirectCode = 302;
|
|
2872
|
+
const requestURL = getRequestURL(event);
|
|
2873
|
+
if (rootRedirect && requestURL.pathname === "/") {
|
|
2874
|
+
locale = detection.enabled && locale || defaultLocale;
|
|
2875
|
+
resolvedPath = isSupportedLocale(detector.route(rootRedirect.path)) && rootRedirect.path || matchLocalized(rootRedirect.path, locale);
|
|
2876
|
+
redirectCode = rootRedirect.code;
|
|
2877
|
+
} else if (runtimeI18n.redirectStatusCode) {
|
|
2878
|
+
redirectCode = runtimeI18n.redirectStatusCode;
|
|
2879
|
+
}
|
|
2880
|
+
switch (detection.redirectOn) {
|
|
2881
|
+
case "root":
|
|
2882
|
+
if (requestURL.pathname !== "/") {
|
|
2883
|
+
break;
|
|
2884
|
+
}
|
|
2885
|
+
// fallthrough (root has no prefix)
|
|
2886
|
+
case "no prefix":
|
|
2887
|
+
if (pathLocale) {
|
|
2888
|
+
break;
|
|
2889
|
+
}
|
|
2890
|
+
// fallthrough to resolve
|
|
2891
|
+
case "all":
|
|
2892
|
+
resolvedPath ??= getLocalizedMatch(locale);
|
|
2893
|
+
break;
|
|
2894
|
+
}
|
|
2895
|
+
if (requestURL.pathname === "/" && "no_prefix" === "prefix") ;
|
|
2896
|
+
return { path: resolvedPath, code: redirectCode, locale };
|
|
2897
|
+
}
|
|
2898
|
+
const baseUrlGetter = createBaseUrlGetter();
|
|
2899
|
+
nitro.hooks.hook("request", async (event) => {
|
|
2900
|
+
await initializeI18nContext(event);
|
|
2901
|
+
});
|
|
2902
|
+
nitro.hooks.hook("render:before", async (context) => {
|
|
2903
|
+
const { event } = context;
|
|
2904
|
+
const ctx = useI18nContext(event);
|
|
2905
|
+
const url = getRequestURL(event);
|
|
2906
|
+
const detector = useDetectors(event, detection);
|
|
2907
|
+
const localeSegment = detector.route(event.path);
|
|
2908
|
+
const pathLocale = isSupportedLocale(localeSegment) && localeSegment || void 0;
|
|
2909
|
+
const path = (pathLocale && url.pathname.slice(pathLocale.length + 1)) ?? url.pathname;
|
|
2910
|
+
if (!url.pathname.includes("/_i18n/YZ5vJeIH") && !isExistingNuxtRoute(path)) {
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2913
|
+
const resolved = resolveRedirectPath(event, path, pathLocale, ctx.vueI18nOptions.defaultLocale, detector);
|
|
2914
|
+
if (resolved.path && resolved.path !== url.pathname) {
|
|
2915
|
+
ctx.detectLocale = resolved.locale;
|
|
2916
|
+
detection.useCookie && setCookie(event, detection.cookieKey, resolved.locale, cookieOptions);
|
|
2917
|
+
context.response = createRedirectResponse(
|
|
2918
|
+
event,
|
|
2919
|
+
joinURL(baseUrlGetter(event, ctx.vueI18nOptions.defaultLocale), resolved.path + url.search),
|
|
2920
|
+
resolved.code
|
|
2921
|
+
);
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
});
|
|
2925
|
+
nitro.hooks.hook("render:html", (htmlContext, { event }) => {
|
|
2926
|
+
tryUseI18nContext(event);
|
|
2927
|
+
});
|
|
2928
|
+
});
|
|
2929
|
+
|
|
2930
|
+
const rootDir = "D:/work/ai-workflow-editor";
|
|
2931
|
+
|
|
2932
|
+
const devReducers = {
|
|
2933
|
+
VNode: (data) => isVNode(data) ? {
|
|
2934
|
+
type: data.type,
|
|
2935
|
+
props: data.props
|
|
2936
|
+
} : undefined,
|
|
2937
|
+
URL: (data) => data instanceof URL ? data.toString() : undefined
|
|
2938
|
+
};
|
|
2939
|
+
const asyncContext = getContext("nuxt-dev", {
|
|
2940
|
+
asyncContext: true,
|
|
2941
|
+
AsyncLocalStorage
|
|
2942
|
+
});
|
|
2943
|
+
const _Ps9lfifg8DXZdQFyt6JEXwuKrVO_YtgD24ygZR22jPo = (nitroApp) => {
|
|
2944
|
+
const handler = nitroApp.h3App.handler;
|
|
2945
|
+
nitroApp.h3App.handler = (event) => {
|
|
2946
|
+
return asyncContext.callAsync({
|
|
2947
|
+
logs: [],
|
|
2948
|
+
event
|
|
2949
|
+
}, () => handler(event));
|
|
2950
|
+
};
|
|
2951
|
+
onConsoleLog((_log) => {
|
|
2952
|
+
const ctx = asyncContext.tryUse();
|
|
2953
|
+
if (!ctx) {
|
|
2954
|
+
return;
|
|
2955
|
+
}
|
|
2956
|
+
const rawStack = captureRawStackTrace();
|
|
2957
|
+
if (!rawStack || rawStack.includes("runtime/vite-node.mjs")) {
|
|
2958
|
+
return;
|
|
2959
|
+
}
|
|
2960
|
+
const trace = [];
|
|
2961
|
+
let filename = "";
|
|
2962
|
+
for (const entry of parseRawStackTrace(rawStack)) {
|
|
2963
|
+
if (entry.source === globalThis._importMeta_.url) {
|
|
2964
|
+
continue;
|
|
2965
|
+
}
|
|
2966
|
+
if (EXCLUDE_TRACE_RE.test(entry.source)) {
|
|
2967
|
+
continue;
|
|
2968
|
+
}
|
|
2969
|
+
filename ||= entry.source.replace(withTrailingSlash(rootDir), "");
|
|
2970
|
+
trace.push({
|
|
2971
|
+
...entry,
|
|
2972
|
+
source: entry.source.startsWith("file://") ? entry.source.replace("file://", "") : entry.source
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
const log = {
|
|
2976
|
+
..._log,
|
|
2977
|
+
filename,
|
|
2978
|
+
stack: trace
|
|
2979
|
+
};
|
|
2980
|
+
// retain log to be include in the next render
|
|
2981
|
+
ctx.logs.push(log);
|
|
2982
|
+
});
|
|
2983
|
+
nitroApp.hooks.hook("afterResponse", () => {
|
|
2984
|
+
const ctx = asyncContext.tryUse();
|
|
2985
|
+
if (!ctx) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
return nitroApp.hooks.callHook("dev:ssr-logs", {
|
|
2989
|
+
logs: ctx.logs,
|
|
2990
|
+
path: ctx.event.path
|
|
2991
|
+
});
|
|
2992
|
+
});
|
|
2993
|
+
// Pass any logs to the client
|
|
2994
|
+
nitroApp.hooks.hook("render:html", (htmlContext) => {
|
|
2995
|
+
const ctx = asyncContext.tryUse();
|
|
2996
|
+
if (!ctx) {
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
try {
|
|
3000
|
+
const reducers = Object.assign(Object.create(null), devReducers, ctx.event.context["~payloadReducers"]);
|
|
3001
|
+
htmlContext.bodyAppend.unshift(`<script type="application/json" data-nuxt-logs="${appId}">${stringify(ctx.logs, reducers)}<\/script>`);
|
|
3002
|
+
} catch (e) {
|
|
3003
|
+
const shortError = e instanceof Error && "toString" in e ? ` Received \`${e.toString()}\`.` : "";
|
|
3004
|
+
console.warn(`[nuxt] Failed to stringify dev server logs.${shortError} You can define your own reducer/reviver for rich types following the instructions in https://nuxt.com/docs/api/composables/use-nuxt-app#payload.`);
|
|
3005
|
+
}
|
|
3006
|
+
});
|
|
3007
|
+
};
|
|
3008
|
+
const EXCLUDE_TRACE_RE = /\/node_modules\/(?:.*\/)?(?:nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/|core\/runtime\/nitro/;
|
|
3009
|
+
function onConsoleLog(callback) {
|
|
3010
|
+
consola$1.addReporter({ log(logObj) {
|
|
3011
|
+
callback(logObj);
|
|
3012
|
+
} });
|
|
3013
|
+
consola$1.wrapConsole();
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
const plugins = [
|
|
3017
|
+
_S7DPrgXM_vAz0MUbsQr9zCWb8lLVJtyoOZQmBzOiis,
|
|
3018
|
+
_zJuKdirGFqxT2wiHdNbvYxI2qOaimipFm38nCQMg4Y,
|
|
3019
|
+
_Ps9lfifg8DXZdQFyt6JEXwuKrVO_YtgD24ygZR22jPo
|
|
3020
|
+
];
|
|
3021
|
+
|
|
3022
|
+
const assets = {};
|
|
3023
|
+
|
|
3024
|
+
function readAsset (id) {
|
|
3025
|
+
const serverDir = dirname$1(fileURLToPath(globalThis._importMeta_.url));
|
|
3026
|
+
return promises.readFile(resolve$1(serverDir, assets[id].path))
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
const publicAssetBases = {"/_nuxt/builds/meta/":{"maxAge":31536000},"/_nuxt/builds/":{"maxAge":1}};
|
|
3030
|
+
|
|
3031
|
+
function isPublicAssetURL(id = '') {
|
|
3032
|
+
if (assets[id]) {
|
|
3033
|
+
return true
|
|
3034
|
+
}
|
|
3035
|
+
for (const base in publicAssetBases) {
|
|
3036
|
+
if (id.startsWith(base)) { return true }
|
|
3037
|
+
}
|
|
3038
|
+
return false
|
|
3039
|
+
}
|
|
3040
|
+
|
|
3041
|
+
function getAsset (id) {
|
|
3042
|
+
return assets[id]
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
const METHODS = /* @__PURE__ */ new Set(["HEAD", "GET"]);
|
|
3046
|
+
const EncodingMap = { gzip: ".gz", br: ".br" };
|
|
3047
|
+
const _lEVQze = eventHandler((event) => {
|
|
3048
|
+
if (event.method && !METHODS.has(event.method)) {
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
let id = decodePath(
|
|
3052
|
+
withLeadingSlash(withoutTrailingSlash(parseURL(event.path).pathname))
|
|
3053
|
+
);
|
|
3054
|
+
let asset;
|
|
3055
|
+
const encodingHeader = String(
|
|
3056
|
+
getRequestHeader(event, "accept-encoding") || ""
|
|
3057
|
+
);
|
|
3058
|
+
const encodings = [
|
|
3059
|
+
...encodingHeader.split(",").map((e) => EncodingMap[e.trim()]).filter(Boolean).sort(),
|
|
3060
|
+
""
|
|
3061
|
+
];
|
|
3062
|
+
for (const encoding of encodings) {
|
|
3063
|
+
for (const _id of [id + encoding, joinURL(id, "index.html" + encoding)]) {
|
|
3064
|
+
const _asset = getAsset(_id);
|
|
3065
|
+
if (_asset) {
|
|
3066
|
+
asset = _asset;
|
|
3067
|
+
id = _id;
|
|
3068
|
+
break;
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
if (!asset) {
|
|
3073
|
+
if (isPublicAssetURL(id)) {
|
|
3074
|
+
removeResponseHeader(event, "Cache-Control");
|
|
3075
|
+
throw createError({ statusCode: 404 });
|
|
3076
|
+
}
|
|
3077
|
+
return;
|
|
3078
|
+
}
|
|
3079
|
+
if (asset.encoding !== void 0) {
|
|
3080
|
+
appendResponseHeader(event, "Vary", "Accept-Encoding");
|
|
3081
|
+
}
|
|
3082
|
+
const ifNotMatch = getRequestHeader(event, "if-none-match") === asset.etag;
|
|
3083
|
+
if (ifNotMatch) {
|
|
3084
|
+
setResponseStatus(event, 304, "Not Modified");
|
|
3085
|
+
return "";
|
|
3086
|
+
}
|
|
3087
|
+
const ifModifiedSinceH = getRequestHeader(event, "if-modified-since");
|
|
3088
|
+
const mtimeDate = new Date(asset.mtime);
|
|
3089
|
+
if (ifModifiedSinceH && asset.mtime && new Date(ifModifiedSinceH) >= mtimeDate) {
|
|
3090
|
+
setResponseStatus(event, 304, "Not Modified");
|
|
3091
|
+
return "";
|
|
3092
|
+
}
|
|
3093
|
+
if (asset.type && !getResponseHeader(event, "Content-Type")) {
|
|
3094
|
+
setResponseHeader(event, "Content-Type", asset.type);
|
|
3095
|
+
}
|
|
3096
|
+
if (asset.etag && !getResponseHeader(event, "ETag")) {
|
|
3097
|
+
setResponseHeader(event, "ETag", asset.etag);
|
|
3098
|
+
}
|
|
3099
|
+
if (asset.mtime && !getResponseHeader(event, "Last-Modified")) {
|
|
3100
|
+
setResponseHeader(event, "Last-Modified", mtimeDate.toUTCString());
|
|
3101
|
+
}
|
|
3102
|
+
if (asset.encoding && !getResponseHeader(event, "Content-Encoding")) {
|
|
3103
|
+
setResponseHeader(event, "Content-Encoding", asset.encoding);
|
|
3104
|
+
}
|
|
3105
|
+
if (asset.size > 0 && !getResponseHeader(event, "Content-Length")) {
|
|
3106
|
+
setResponseHeader(event, "Content-Length", asset.size);
|
|
3107
|
+
}
|
|
3108
|
+
return readAsset(id);
|
|
3109
|
+
});
|
|
3110
|
+
|
|
3111
|
+
const VueResolver = (_, value) => {
|
|
3112
|
+
return isRef(value) ? toValue(value) : value;
|
|
3113
|
+
};
|
|
3114
|
+
|
|
3115
|
+
const headSymbol = "usehead";
|
|
3116
|
+
// @__NO_SIDE_EFFECTS__
|
|
3117
|
+
function vueInstall(head) {
|
|
3118
|
+
const plugin = {
|
|
3119
|
+
install(app) {
|
|
3120
|
+
app.config.globalProperties.$unhead = head;
|
|
3121
|
+
app.config.globalProperties.$head = head;
|
|
3122
|
+
app.provide(headSymbol, head);
|
|
3123
|
+
}
|
|
3124
|
+
};
|
|
3125
|
+
return plugin.install;
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
// @__NO_SIDE_EFFECTS__
|
|
3129
|
+
function resolveUnrefHeadInput(input) {
|
|
3130
|
+
return walkResolver(input, VueResolver);
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
const NUXT_RUNTIME_PAYLOAD_EXTRACTION = false;
|
|
3134
|
+
|
|
3135
|
+
// @__NO_SIDE_EFFECTS__
|
|
3136
|
+
function createHead(options = {}) {
|
|
3137
|
+
const head = createHead$1({
|
|
3138
|
+
...options,
|
|
3139
|
+
propResolvers: [VueResolver]
|
|
3140
|
+
});
|
|
3141
|
+
head.install = vueInstall(head);
|
|
3142
|
+
return head;
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
const unheadOptions = {
|
|
3146
|
+
disableDefaults: true,
|
|
3147
|
+
disableCapoSorting: false,
|
|
3148
|
+
plugins: [DeprecationsPlugin, PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin],
|
|
3149
|
+
};
|
|
3150
|
+
|
|
3151
|
+
function createSSRContext(event) {
|
|
3152
|
+
const ssrContext = {
|
|
3153
|
+
url: event.path,
|
|
3154
|
+
event,
|
|
3155
|
+
runtimeConfig: useRuntimeConfig(event),
|
|
3156
|
+
noSSR: event.context.nuxt?.noSSR || (false),
|
|
3157
|
+
head: createHead(unheadOptions),
|
|
3158
|
+
error: false,
|
|
3159
|
+
nuxt: undefined,
|
|
3160
|
+
payload: {},
|
|
3161
|
+
["~payloadReducers"]: Object.create(null),
|
|
3162
|
+
modules: new Set()
|
|
3163
|
+
};
|
|
3164
|
+
return ssrContext;
|
|
3165
|
+
}
|
|
3166
|
+
function setSSRError(ssrContext, error) {
|
|
3167
|
+
ssrContext.error = true;
|
|
3168
|
+
ssrContext.payload = { error };
|
|
3169
|
+
ssrContext.url = error.url;
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
const APP_ROOT_OPEN_TAG = `<${appRootTag}${propsToString(appRootAttrs)}>`;
|
|
3173
|
+
const APP_ROOT_CLOSE_TAG = `</${appRootTag}>`;
|
|
3174
|
+
// @ts-expect-error file will be produced after app build
|
|
3175
|
+
const getServerEntry = () => import('file://D:/work/ai-workflow-editor/.nuxt//dist/server/server.mjs').then((r) => r.default || r);
|
|
3176
|
+
// @ts-expect-error file will be produced after app build
|
|
3177
|
+
const getClientManifest = () => import('file://D:/work/ai-workflow-editor/.nuxt//dist/server/client.manifest.mjs').then((r) => r.default || r).then((r) => typeof r === "function" ? r() : r);
|
|
3178
|
+
// -- SSR Renderer --
|
|
3179
|
+
const getSSRRenderer = lazyCachedFunction(async () => {
|
|
3180
|
+
// Load server bundle
|
|
3181
|
+
const createSSRApp = await getServerEntry();
|
|
3182
|
+
if (!createSSRApp) {
|
|
3183
|
+
throw new Error("Server bundle is not available");
|
|
3184
|
+
}
|
|
3185
|
+
// Load precomputed dependencies
|
|
3186
|
+
const precomputed = undefined ;
|
|
3187
|
+
// Create renderer
|
|
3188
|
+
const renderer = createRenderer(createSSRApp, {
|
|
3189
|
+
precomputed,
|
|
3190
|
+
manifest: await getClientManifest() ,
|
|
3191
|
+
renderToString: renderToString$1,
|
|
3192
|
+
buildAssetsURL
|
|
3193
|
+
});
|
|
3194
|
+
async function renderToString$1(input, context) {
|
|
3195
|
+
const html = await renderToString(input, context);
|
|
3196
|
+
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
|
3197
|
+
// eslint-disable-next-line no-restricted-globals
|
|
3198
|
+
if (process.env.NUXT_VITE_NODE_OPTIONS) {
|
|
3199
|
+
renderer.rendererContext.updateManifest(await getClientManifest());
|
|
3200
|
+
}
|
|
3201
|
+
return APP_ROOT_OPEN_TAG + html + APP_ROOT_CLOSE_TAG;
|
|
3202
|
+
}
|
|
3203
|
+
return renderer;
|
|
3204
|
+
});
|
|
3205
|
+
// -- SPA Renderer --
|
|
3206
|
+
const getSPARenderer = lazyCachedFunction(async () => {
|
|
3207
|
+
const precomputed = undefined ;
|
|
3208
|
+
// @ts-expect-error virtual file
|
|
3209
|
+
const spaTemplate = await Promise.resolve().then(function () { return _virtual__spaTemplate; }).then((r) => r.template).catch(() => "").then((r) => {
|
|
3210
|
+
{
|
|
3211
|
+
return APP_ROOT_OPEN_TAG + r + APP_ROOT_CLOSE_TAG;
|
|
3212
|
+
}
|
|
3213
|
+
});
|
|
3214
|
+
// Create SPA renderer and cache the result for all requests
|
|
3215
|
+
const renderer = createRenderer(() => () => {}, {
|
|
3216
|
+
precomputed,
|
|
3217
|
+
manifest: await getClientManifest() ,
|
|
3218
|
+
renderToString: () => spaTemplate,
|
|
3219
|
+
buildAssetsURL
|
|
3220
|
+
});
|
|
3221
|
+
const result = await renderer.renderToString({});
|
|
3222
|
+
const renderToString = (ssrContext) => {
|
|
3223
|
+
const config = useRuntimeConfig(ssrContext.event);
|
|
3224
|
+
ssrContext.modules ||= new Set();
|
|
3225
|
+
ssrContext.payload.serverRendered = false;
|
|
3226
|
+
ssrContext.config = {
|
|
3227
|
+
public: config.public,
|
|
3228
|
+
app: config.app
|
|
3229
|
+
};
|
|
3230
|
+
return Promise.resolve(result);
|
|
3231
|
+
};
|
|
3232
|
+
return {
|
|
3233
|
+
rendererContext: renderer.rendererContext,
|
|
3234
|
+
renderToString
|
|
3235
|
+
};
|
|
3236
|
+
});
|
|
3237
|
+
function lazyCachedFunction(fn) {
|
|
3238
|
+
let res = null;
|
|
3239
|
+
return () => {
|
|
3240
|
+
if (res === null) {
|
|
3241
|
+
res = fn().catch((err) => {
|
|
3242
|
+
res = null;
|
|
3243
|
+
throw err;
|
|
3244
|
+
});
|
|
3245
|
+
}
|
|
3246
|
+
return res;
|
|
3247
|
+
};
|
|
3248
|
+
}
|
|
3249
|
+
function getRenderer(ssrContext) {
|
|
3250
|
+
return ssrContext.noSSR ? getSPARenderer() : getSSRRenderer();
|
|
3251
|
+
}
|
|
3252
|
+
// @ts-expect-error file will be produced after app build
|
|
3253
|
+
const getSSRStyles = lazyCachedFunction(() => Promise.resolve().then(function () { return styles$1; }).then((r) => r.default || r));
|
|
3254
|
+
|
|
3255
|
+
async function renderInlineStyles(usedModules) {
|
|
3256
|
+
const styleMap = await getSSRStyles();
|
|
3257
|
+
const inlinedStyles = new Set();
|
|
3258
|
+
for (const mod of usedModules) {
|
|
3259
|
+
if (mod in styleMap && styleMap[mod]) {
|
|
3260
|
+
for (const style of await styleMap[mod]()) {
|
|
3261
|
+
inlinedStyles.add(style);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
return Array.from(inlinedStyles).map((style) => ({ innerHTML: style }));
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
// @ts-expect-error virtual file
|
|
3269
|
+
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}[^>]*>([\\s\\S]*)<\\/${appRootTag}>$`);
|
|
3270
|
+
/**
|
|
3271
|
+
* remove the root node from the html body
|
|
3272
|
+
*/
|
|
3273
|
+
function getServerComponentHTML(body) {
|
|
3274
|
+
const match = body.match(ROOT_NODE_REGEX);
|
|
3275
|
+
return match?.[1] || body;
|
|
3276
|
+
}
|
|
3277
|
+
const SSR_SLOT_TELEPORT_MARKER = /^uid=([^;]*);slot=(.*)$/;
|
|
3278
|
+
const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/;
|
|
3279
|
+
const SSR_CLIENT_SLOT_MARKER = /^island-slot=([^;]*);(.*)$/;
|
|
3280
|
+
function getSlotIslandResponse(ssrContext) {
|
|
3281
|
+
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) {
|
|
3282
|
+
return undefined;
|
|
3283
|
+
}
|
|
3284
|
+
const response = {};
|
|
3285
|
+
for (const [name, slot] of Object.entries(ssrContext.islandContext.slots)) {
|
|
3286
|
+
response[name] = {
|
|
3287
|
+
...slot,
|
|
3288
|
+
fallback: ssrContext.teleports?.[`island-fallback=${name}`]
|
|
3289
|
+
};
|
|
3290
|
+
}
|
|
3291
|
+
return response;
|
|
3292
|
+
}
|
|
3293
|
+
function getClientIslandResponse(ssrContext) {
|
|
3294
|
+
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) {
|
|
3295
|
+
return undefined;
|
|
3296
|
+
}
|
|
3297
|
+
const response = {};
|
|
3298
|
+
for (const [clientUid, component] of Object.entries(ssrContext.islandContext.components)) {
|
|
3299
|
+
// remove teleport anchor to avoid hydration issues
|
|
3300
|
+
const html = ssrContext.teleports?.[clientUid]?.replaceAll("<!--teleport start anchor-->", "") || "";
|
|
3301
|
+
response[clientUid] = {
|
|
3302
|
+
...component,
|
|
3303
|
+
html,
|
|
3304
|
+
slots: getComponentSlotTeleport(clientUid, ssrContext.teleports ?? {})
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
return response;
|
|
3308
|
+
}
|
|
3309
|
+
function getComponentSlotTeleport(clientUid, teleports) {
|
|
3310
|
+
const entries = Object.entries(teleports);
|
|
3311
|
+
const slots = {};
|
|
3312
|
+
for (const [key, value] of entries) {
|
|
3313
|
+
const match = key.match(SSR_CLIENT_SLOT_MARKER);
|
|
3314
|
+
if (match) {
|
|
3315
|
+
const [, id, slot] = match;
|
|
3316
|
+
if (!slot || clientUid !== id) {
|
|
3317
|
+
continue;
|
|
3318
|
+
}
|
|
3319
|
+
slots[slot] = value;
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
return slots;
|
|
3323
|
+
}
|
|
3324
|
+
function replaceIslandTeleports(ssrContext, html) {
|
|
3325
|
+
const { teleports, islandContext } = ssrContext;
|
|
3326
|
+
if (islandContext || !teleports) {
|
|
3327
|
+
return html;
|
|
3328
|
+
}
|
|
3329
|
+
for (const key in teleports) {
|
|
3330
|
+
const matchClientComp = key.match(SSR_CLIENT_TELEPORT_MARKER);
|
|
3331
|
+
if (matchClientComp) {
|
|
3332
|
+
const [, uid, clientId] = matchClientComp;
|
|
3333
|
+
if (!uid || !clientId) {
|
|
3334
|
+
continue;
|
|
3335
|
+
}
|
|
3336
|
+
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-component="${clientId}"[^>]*>`), (full) => {
|
|
3337
|
+
return full + teleports[key];
|
|
3338
|
+
});
|
|
3339
|
+
continue;
|
|
3340
|
+
}
|
|
3341
|
+
const matchSlot = key.match(SSR_SLOT_TELEPORT_MARKER);
|
|
3342
|
+
if (matchSlot) {
|
|
3343
|
+
const [, uid, slot] = matchSlot;
|
|
3344
|
+
if (!uid || !slot) {
|
|
3345
|
+
continue;
|
|
3346
|
+
}
|
|
3347
|
+
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-slot="${slot}"[^>]*>`), (full) => {
|
|
3348
|
+
return full + teleports[key];
|
|
3349
|
+
});
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
return html;
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
const ISLAND_SUFFIX_RE = /\.json(?:\?.*)?$/;
|
|
3356
|
+
const _SxA8c9 = defineEventHandler(async (event) => {
|
|
3357
|
+
const nitroApp = useNitroApp();
|
|
3358
|
+
setResponseHeaders(event, {
|
|
3359
|
+
"content-type": "application/json;charset=utf-8",
|
|
3360
|
+
"x-powered-by": "Nuxt"
|
|
3361
|
+
});
|
|
3362
|
+
const islandContext = await getIslandContext(event);
|
|
3363
|
+
const ssrContext = {
|
|
3364
|
+
...createSSRContext(event),
|
|
3365
|
+
islandContext,
|
|
3366
|
+
noSSR: false,
|
|
3367
|
+
url: islandContext.url
|
|
3368
|
+
};
|
|
3369
|
+
// Render app
|
|
3370
|
+
const renderer = await getSSRRenderer();
|
|
3371
|
+
const renderResult = await renderer.renderToString(ssrContext).catch(async (err) => {
|
|
3372
|
+
await ssrContext.nuxt?.hooks.callHook("app:error", err);
|
|
3373
|
+
throw err;
|
|
3374
|
+
});
|
|
3375
|
+
// Handle errors
|
|
3376
|
+
if (ssrContext.payload?.error) {
|
|
3377
|
+
throw ssrContext.payload.error;
|
|
3378
|
+
}
|
|
3379
|
+
const inlinedStyles = await renderInlineStyles(ssrContext.modules ?? []);
|
|
3380
|
+
await ssrContext.nuxt?.hooks.callHook("app:rendered", {
|
|
3381
|
+
ssrContext,
|
|
3382
|
+
renderResult
|
|
3383
|
+
});
|
|
3384
|
+
if (inlinedStyles.length) {
|
|
3385
|
+
ssrContext.head.push({ style: inlinedStyles });
|
|
3386
|
+
}
|
|
3387
|
+
{
|
|
3388
|
+
const { styles } = getRequestDependencies(ssrContext, renderer.rendererContext);
|
|
3389
|
+
const link = [];
|
|
3390
|
+
for (const resource of Object.values(styles)) {
|
|
3391
|
+
// Do not add links to resources that are inlined (vite v5+)
|
|
3392
|
+
if ("inline" in getQuery(resource.file)) {
|
|
3393
|
+
continue;
|
|
3394
|
+
}
|
|
3395
|
+
// Add CSS links in <head> for CSS files
|
|
3396
|
+
// - in dev mode when rendering an island and the file has scoped styles and is not a page
|
|
3397
|
+
if (resource.file.includes("scoped") && !resource.file.includes("pages/")) {
|
|
3398
|
+
link.push({
|
|
3399
|
+
rel: "stylesheet",
|
|
3400
|
+
href: renderer.rendererContext.buildAssetsURL(resource.file),
|
|
3401
|
+
crossorigin: ""
|
|
3402
|
+
});
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
if (link.length) {
|
|
3406
|
+
ssrContext.head.push({ link }, { mode: "server" });
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
const islandHead = {};
|
|
3410
|
+
for (const entry of ssrContext.head.entries.values()) {
|
|
3411
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
3412
|
+
for (const [key, value] of Object.entries(resolveUnrefHeadInput(entry.input))) {
|
|
3413
|
+
const currentValue = islandHead[key];
|
|
3414
|
+
if (Array.isArray(currentValue)) {
|
|
3415
|
+
currentValue.push(...value);
|
|
3416
|
+
} else {
|
|
3417
|
+
islandHead[key] = value;
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
// TODO: remove for v4
|
|
3422
|
+
islandHead.link ||= [];
|
|
3423
|
+
islandHead.style ||= [];
|
|
3424
|
+
const islandResponse = {
|
|
3425
|
+
id: islandContext.id,
|
|
3426
|
+
head: islandHead,
|
|
3427
|
+
html: getServerComponentHTML(renderResult.html),
|
|
3428
|
+
components: getClientIslandResponse(ssrContext),
|
|
3429
|
+
slots: getSlotIslandResponse(ssrContext)
|
|
3430
|
+
};
|
|
3431
|
+
await nitroApp.hooks.callHook("render:island", islandResponse, {
|
|
3432
|
+
event,
|
|
3433
|
+
islandContext
|
|
3434
|
+
});
|
|
3435
|
+
return islandResponse;
|
|
3436
|
+
});
|
|
3437
|
+
async function getIslandContext(event) {
|
|
3438
|
+
// TODO: Strict validation for url
|
|
3439
|
+
let url = event.path || "";
|
|
3440
|
+
const componentParts = url.substring("/__nuxt_island".length + 1).replace(ISLAND_SUFFIX_RE, "").split("_");
|
|
3441
|
+
const hashId = componentParts.length > 1 ? componentParts.pop() : undefined;
|
|
3442
|
+
const componentName = componentParts.join("_");
|
|
3443
|
+
// TODO: Validate context
|
|
3444
|
+
const context = event.method === "GET" ? getQuery$1(event) : await readBody(event);
|
|
3445
|
+
const ctx = {
|
|
3446
|
+
url: "/",
|
|
3447
|
+
...context,
|
|
3448
|
+
id: hashId,
|
|
3449
|
+
name: componentName,
|
|
3450
|
+
props: destr$1(context.props) || {},
|
|
3451
|
+
slots: {},
|
|
3452
|
+
components: {}
|
|
3453
|
+
};
|
|
3454
|
+
return ctx;
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
const storage = prefixStorage(useStorage(), "i18n");
|
|
3458
|
+
function cachedFunctionI18n(fn, opts) {
|
|
3459
|
+
opts = { maxAge: 1, ...opts };
|
|
3460
|
+
const pending = {};
|
|
3461
|
+
async function get(key, resolver) {
|
|
3462
|
+
const isPending = pending[key];
|
|
3463
|
+
if (!isPending) {
|
|
3464
|
+
pending[key] = Promise.resolve(resolver());
|
|
3465
|
+
}
|
|
3466
|
+
try {
|
|
3467
|
+
return await pending[key];
|
|
3468
|
+
} finally {
|
|
3469
|
+
delete pending[key];
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
return async (...args) => {
|
|
3473
|
+
const key = [opts.name, opts.getKey(...args)].join(":").replace(/:\/$/, ":index");
|
|
3474
|
+
const maxAge = opts.maxAge ?? 1;
|
|
3475
|
+
const isCacheable = !opts.shouldBypassCache(...args) && maxAge >= 0;
|
|
3476
|
+
const cache = isCacheable && await storage.getItemRaw(key);
|
|
3477
|
+
if (!cache || cache.ttl < Date.now()) {
|
|
3478
|
+
pending[key] = Promise.resolve(fn(...args));
|
|
3479
|
+
const value = await get(key, () => fn(...args));
|
|
3480
|
+
if (isCacheable) {
|
|
3481
|
+
await storage.setItemRaw(key, { ttl: Date.now() + maxAge * 1e3, value, mtime: Date.now() });
|
|
3482
|
+
}
|
|
3483
|
+
return value;
|
|
3484
|
+
}
|
|
3485
|
+
return cache.value;
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3489
|
+
const _getMessages = async (locale) => {
|
|
3490
|
+
return { [locale]: await getLocaleMessagesMerged(locale, localeLoaders[locale]) };
|
|
3491
|
+
};
|
|
3492
|
+
cachedFunctionI18n(_getMessages, {
|
|
3493
|
+
name: "messages",
|
|
3494
|
+
maxAge: -1 ,
|
|
3495
|
+
getKey: (locale) => locale,
|
|
3496
|
+
shouldBypassCache: (locale) => !isLocaleCacheable(locale)
|
|
3497
|
+
});
|
|
3498
|
+
const getMessages = _getMessages ;
|
|
3499
|
+
const _getMergedMessages = async (locale, fallbackLocales) => {
|
|
3500
|
+
const merged = {};
|
|
3501
|
+
try {
|
|
3502
|
+
if (fallbackLocales.length > 0) {
|
|
3503
|
+
const messages = await Promise.all(fallbackLocales.map(getMessages));
|
|
3504
|
+
for (const message2 of messages) {
|
|
3505
|
+
deepCopy(message2, merged);
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
const message = await getMessages(locale);
|
|
3509
|
+
deepCopy(message, merged);
|
|
3510
|
+
return merged;
|
|
3511
|
+
} catch (e) {
|
|
3512
|
+
throw new Error("Failed to merge messages: " + e.message);
|
|
3513
|
+
}
|
|
3514
|
+
};
|
|
3515
|
+
const getMergedMessages = cachedFunctionI18n(_getMergedMessages, {
|
|
3516
|
+
name: "merged-single",
|
|
3517
|
+
maxAge: -1 ,
|
|
3518
|
+
getKey: (locale, fallbackLocales) => `${locale}-[${[...new Set(fallbackLocales)].sort().join("-")}]`,
|
|
3519
|
+
shouldBypassCache: (locale, fallbackLocales) => !isLocaleWithFallbacksCacheable(locale, fallbackLocales)
|
|
3520
|
+
});
|
|
3521
|
+
const _getAllMergedMessages = async (locales) => {
|
|
3522
|
+
const merged = {};
|
|
3523
|
+
try {
|
|
3524
|
+
const messages = await Promise.all(locales.map(getMessages));
|
|
3525
|
+
for (const message of messages) {
|
|
3526
|
+
deepCopy(message, merged);
|
|
3527
|
+
}
|
|
3528
|
+
return merged;
|
|
3529
|
+
} catch (e) {
|
|
3530
|
+
throw new Error("Failed to merge messages: " + e.message);
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
cachedFunctionI18n(_getAllMergedMessages, {
|
|
3534
|
+
name: "merged-all",
|
|
3535
|
+
maxAge: -1 ,
|
|
3536
|
+
getKey: (locales) => locales.join("-"),
|
|
3537
|
+
shouldBypassCache: (locales) => !locales.every((locale) => isLocaleCacheable(locale))
|
|
3538
|
+
});
|
|
3539
|
+
|
|
3540
|
+
const _messagesHandler = defineEventHandler(async (event) => {
|
|
3541
|
+
const locale = getRouterParam(event, "locale");
|
|
3542
|
+
if (!locale) {
|
|
3543
|
+
throw createError({ status: 400, message: "Locale not specified." });
|
|
3544
|
+
}
|
|
3545
|
+
const ctx = useI18nContext(event);
|
|
3546
|
+
if (ctx.localeConfigs && locale in ctx.localeConfigs === false) {
|
|
3547
|
+
throw createError({ status: 404, message: `Locale '${locale}' not found.` });
|
|
3548
|
+
}
|
|
3549
|
+
const messages = await getMergedMessages(locale, ctx.localeConfigs?.[locale]?.fallbacks ?? []);
|
|
3550
|
+
deepCopy(messages, ctx.messages);
|
|
3551
|
+
return ctx.messages;
|
|
3552
|
+
});
|
|
3553
|
+
const _cachedMessageLoader = defineCachedFunction(_messagesHandler, {
|
|
3554
|
+
name: "i18n:messages-internal",
|
|
3555
|
+
maxAge: -1 ,
|
|
3556
|
+
getKey: (event) => [getRouterParam(event, "locale") ?? "null", getRouterParam(event, "hash") ?? "null"].join("-"),
|
|
3557
|
+
async shouldBypassCache(event) {
|
|
3558
|
+
const locale = getRouterParam(event, "locale");
|
|
3559
|
+
if (locale == null) {
|
|
3560
|
+
return false;
|
|
3561
|
+
}
|
|
3562
|
+
const ctx = tryUseI18nContext(event) || await initializeI18nContext(event);
|
|
3563
|
+
return !ctx.localeConfigs?.[locale]?.cacheable;
|
|
3564
|
+
}
|
|
3565
|
+
});
|
|
3566
|
+
defineCachedEventHandler(_cachedMessageLoader, {
|
|
3567
|
+
name: "i18n:messages",
|
|
3568
|
+
maxAge: -1 ,
|
|
3569
|
+
swr: false,
|
|
3570
|
+
getKey: (event) => [getRouterParam(event, "locale") ?? "null", getRouterParam(event, "hash") ?? "null"].join("-")
|
|
3571
|
+
});
|
|
3572
|
+
const _v0_q3F = _messagesHandler ;
|
|
3573
|
+
|
|
3574
|
+
const _lazy_ia6fyf = () => Promise.resolve().then(function () { return renderer$1; });
|
|
3575
|
+
|
|
3576
|
+
const handlers = [
|
|
3577
|
+
{ route: '', handler: _lEVQze, lazy: false, middleware: true, method: undefined },
|
|
3578
|
+
{ route: '/__nuxt_error', handler: _lazy_ia6fyf, lazy: true, middleware: false, method: undefined },
|
|
3579
|
+
{ route: '/__nuxt_island/**', handler: _SxA8c9, lazy: false, middleware: false, method: undefined },
|
|
3580
|
+
{ route: '/_i18n/:hash/:locale/messages.json', handler: _v0_q3F, lazy: false, middleware: false, method: undefined },
|
|
3581
|
+
{ route: '/**', handler: _lazy_ia6fyf, lazy: true, middleware: false, method: undefined }
|
|
3582
|
+
];
|
|
3583
|
+
|
|
3584
|
+
function createNitroApp() {
|
|
3585
|
+
const config = useRuntimeConfig();
|
|
3586
|
+
const hooks = createHooks();
|
|
3587
|
+
const captureError = (error, context = {}) => {
|
|
3588
|
+
const promise = hooks.callHookParallel("error", error, context).catch((error_) => {
|
|
3589
|
+
console.error("Error while capturing another error", error_);
|
|
3590
|
+
});
|
|
3591
|
+
if (context.event && isEvent(context.event)) {
|
|
3592
|
+
const errors = context.event.context.nitro?.errors;
|
|
3593
|
+
if (errors) {
|
|
3594
|
+
errors.push({ error, context });
|
|
3595
|
+
}
|
|
3596
|
+
if (context.event.waitUntil) {
|
|
3597
|
+
context.event.waitUntil(promise);
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
};
|
|
3601
|
+
const h3App = createApp({
|
|
3602
|
+
debug: destr(true),
|
|
3603
|
+
onError: (error, event) => {
|
|
3604
|
+
captureError(error, { event, tags: ["request"] });
|
|
3605
|
+
return errorHandler(error, event);
|
|
3606
|
+
},
|
|
3607
|
+
onRequest: async (event) => {
|
|
3608
|
+
event.context.nitro = event.context.nitro || { errors: [] };
|
|
3609
|
+
const fetchContext = event.node.req?.__unenv__;
|
|
3610
|
+
if (fetchContext?._platform) {
|
|
3611
|
+
event.context = {
|
|
3612
|
+
_platform: fetchContext?._platform,
|
|
3613
|
+
// #3335
|
|
3614
|
+
...fetchContext._platform,
|
|
3615
|
+
...event.context
|
|
3616
|
+
};
|
|
3617
|
+
}
|
|
3618
|
+
if (!event.context.waitUntil && fetchContext?.waitUntil) {
|
|
3619
|
+
event.context.waitUntil = fetchContext.waitUntil;
|
|
3620
|
+
}
|
|
3621
|
+
event.fetch = (req, init) => fetchWithEvent(event, req, init, { fetch: localFetch });
|
|
3622
|
+
event.$fetch = (req, init) => fetchWithEvent(event, req, init, {
|
|
3623
|
+
fetch: $fetch
|
|
3624
|
+
});
|
|
3625
|
+
event.waitUntil = (promise) => {
|
|
3626
|
+
if (!event.context.nitro._waitUntilPromises) {
|
|
3627
|
+
event.context.nitro._waitUntilPromises = [];
|
|
3628
|
+
}
|
|
3629
|
+
event.context.nitro._waitUntilPromises.push(promise);
|
|
3630
|
+
if (event.context.waitUntil) {
|
|
3631
|
+
event.context.waitUntil(promise);
|
|
3632
|
+
}
|
|
3633
|
+
};
|
|
3634
|
+
event.captureError = (error, context) => {
|
|
3635
|
+
captureError(error, { event, ...context });
|
|
3636
|
+
};
|
|
3637
|
+
await nitroApp$1.hooks.callHook("request", event).catch((error) => {
|
|
3638
|
+
captureError(error, { event, tags: ["request"] });
|
|
3639
|
+
});
|
|
3640
|
+
},
|
|
3641
|
+
onBeforeResponse: async (event, response) => {
|
|
3642
|
+
await nitroApp$1.hooks.callHook("beforeResponse", event, response).catch((error) => {
|
|
3643
|
+
captureError(error, { event, tags: ["request", "response"] });
|
|
3644
|
+
});
|
|
3645
|
+
},
|
|
3646
|
+
onAfterResponse: async (event, response) => {
|
|
3647
|
+
await nitroApp$1.hooks.callHook("afterResponse", event, response).catch((error) => {
|
|
3648
|
+
captureError(error, { event, tags: ["request", "response"] });
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
});
|
|
3652
|
+
const router = createRouter$1({
|
|
3653
|
+
preemptive: true
|
|
3654
|
+
});
|
|
3655
|
+
const nodeHandler = toNodeListener(h3App);
|
|
3656
|
+
const localCall = (aRequest) => callNodeRequestHandler(
|
|
3657
|
+
nodeHandler,
|
|
3658
|
+
aRequest
|
|
3659
|
+
);
|
|
3660
|
+
const localFetch = (input, init) => {
|
|
3661
|
+
if (!input.toString().startsWith("/")) {
|
|
3662
|
+
return globalThis.fetch(input, init);
|
|
3663
|
+
}
|
|
3664
|
+
return fetchNodeRequestHandler(
|
|
3665
|
+
nodeHandler,
|
|
3666
|
+
input,
|
|
3667
|
+
init
|
|
3668
|
+
).then((response) => normalizeFetchResponse(response));
|
|
3669
|
+
};
|
|
3670
|
+
const $fetch = createFetch({
|
|
3671
|
+
fetch: localFetch,
|
|
3672
|
+
Headers: Headers$1,
|
|
3673
|
+
defaults: { baseURL: config.app.baseURL }
|
|
3674
|
+
});
|
|
3675
|
+
globalThis.$fetch = $fetch;
|
|
3676
|
+
h3App.use(createRouteRulesHandler({ localFetch }));
|
|
3677
|
+
for (const h of handlers) {
|
|
3678
|
+
let handler = h.lazy ? lazyEventHandler(h.handler) : h.handler;
|
|
3679
|
+
if (h.middleware || !h.route) {
|
|
3680
|
+
const middlewareBase = (config.app.baseURL + (h.route || "/")).replace(
|
|
3681
|
+
/\/+/g,
|
|
3682
|
+
"/"
|
|
3683
|
+
);
|
|
3684
|
+
h3App.use(middlewareBase, handler);
|
|
3685
|
+
} else {
|
|
3686
|
+
const routeRules = getRouteRulesForPath(
|
|
3687
|
+
h.route.replace(/:\w+|\*\*/g, "_")
|
|
3688
|
+
);
|
|
3689
|
+
if (routeRules.cache) {
|
|
3690
|
+
handler = cachedEventHandler(handler, {
|
|
3691
|
+
group: "nitro/routes",
|
|
3692
|
+
...routeRules.cache
|
|
3693
|
+
});
|
|
3694
|
+
}
|
|
3695
|
+
router.use(h.route, handler, h.method);
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
h3App.use(config.app.baseURL, router.handler);
|
|
3699
|
+
const app = {
|
|
3700
|
+
hooks,
|
|
3701
|
+
h3App,
|
|
3702
|
+
router,
|
|
3703
|
+
localCall,
|
|
3704
|
+
localFetch,
|
|
3705
|
+
captureError
|
|
3706
|
+
};
|
|
3707
|
+
return app;
|
|
3708
|
+
}
|
|
3709
|
+
function runNitroPlugins(nitroApp2) {
|
|
3710
|
+
for (const plugin of plugins) {
|
|
3711
|
+
try {
|
|
3712
|
+
plugin(nitroApp2);
|
|
3713
|
+
} catch (error) {
|
|
3714
|
+
nitroApp2.captureError(error, { tags: ["plugin"] });
|
|
3715
|
+
throw error;
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
const nitroApp$1 = createNitroApp();
|
|
3720
|
+
function useNitroApp() {
|
|
3721
|
+
return nitroApp$1;
|
|
3722
|
+
}
|
|
3723
|
+
runNitroPlugins(nitroApp$1);
|
|
3724
|
+
|
|
3725
|
+
if (!globalThis.crypto) {
|
|
3726
|
+
globalThis.crypto = nodeCrypto.webcrypto;
|
|
3727
|
+
}
|
|
3728
|
+
const { NITRO_NO_UNIX_SOCKET, NITRO_DEV_WORKER_ID } = process.env;
|
|
3729
|
+
trapUnhandledNodeErrors();
|
|
3730
|
+
parentPort?.on("message", (msg) => {
|
|
3731
|
+
if (msg && msg.event === "shutdown") {
|
|
3732
|
+
shutdown();
|
|
3733
|
+
}
|
|
3734
|
+
});
|
|
3735
|
+
const nitroApp = useNitroApp();
|
|
3736
|
+
const server = new Server(toNodeListener(nitroApp.h3App));
|
|
3737
|
+
let listener;
|
|
3738
|
+
listen().catch(() => listen(
|
|
3739
|
+
true
|
|
3740
|
+
/* use random port */
|
|
3741
|
+
)).catch((error) => {
|
|
3742
|
+
console.error("Dev worker failed to listen:", error);
|
|
3743
|
+
return shutdown();
|
|
3744
|
+
});
|
|
3745
|
+
nitroApp.router.get(
|
|
3746
|
+
"/_nitro/tasks",
|
|
3747
|
+
defineEventHandler(async (event) => {
|
|
3748
|
+
const _tasks = await Promise.all(
|
|
3749
|
+
Object.entries(tasks).map(async ([name, task]) => {
|
|
3750
|
+
const _task = await task.resolve?.();
|
|
3751
|
+
return [name, { description: _task?.meta?.description }];
|
|
3752
|
+
})
|
|
3753
|
+
);
|
|
3754
|
+
return {
|
|
3755
|
+
tasks: Object.fromEntries(_tasks),
|
|
3756
|
+
scheduledTasks
|
|
3757
|
+
};
|
|
3758
|
+
})
|
|
3759
|
+
);
|
|
3760
|
+
nitroApp.router.use(
|
|
3761
|
+
"/_nitro/tasks/:name",
|
|
3762
|
+
defineEventHandler(async (event) => {
|
|
3763
|
+
const name = getRouterParam(event, "name");
|
|
3764
|
+
const payload = {
|
|
3765
|
+
...getQuery$1(event),
|
|
3766
|
+
...await readBody(event).then((r) => r?.payload).catch(() => ({}))
|
|
3767
|
+
};
|
|
3768
|
+
return await runTask(name, { payload });
|
|
3769
|
+
})
|
|
3770
|
+
);
|
|
3771
|
+
function listen(useRandomPort = Boolean(
|
|
3772
|
+
NITRO_NO_UNIX_SOCKET || process.versions.webcontainer || "Bun" in globalThis && process.platform === "win32"
|
|
3773
|
+
)) {
|
|
3774
|
+
return new Promise((resolve, reject) => {
|
|
3775
|
+
try {
|
|
3776
|
+
listener = server.listen(useRandomPort ? 0 : getSocketAddress(), () => {
|
|
3777
|
+
const address = server.address();
|
|
3778
|
+
parentPort?.postMessage({
|
|
3779
|
+
event: "listen",
|
|
3780
|
+
address: typeof address === "string" ? { socketPath: address } : { host: "localhost", port: address?.port }
|
|
3781
|
+
});
|
|
3782
|
+
resolve();
|
|
3783
|
+
});
|
|
3784
|
+
} catch (error) {
|
|
3785
|
+
reject(error);
|
|
3786
|
+
}
|
|
3787
|
+
});
|
|
3788
|
+
}
|
|
3789
|
+
function getSocketAddress() {
|
|
3790
|
+
const socketName = `nitro-worker-${process.pid}-${threadId}-${NITRO_DEV_WORKER_ID}-${Math.round(Math.random() * 1e4)}.sock`;
|
|
3791
|
+
if (process.platform === "win32") {
|
|
3792
|
+
return join(String.raw`\\.\pipe`, socketName);
|
|
3793
|
+
}
|
|
3794
|
+
if (process.platform === "linux") {
|
|
3795
|
+
const nodeMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
|
|
3796
|
+
if (nodeMajor >= 20) {
|
|
3797
|
+
return `\0${socketName}`;
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
return join(tmpdir(), socketName);
|
|
3801
|
+
}
|
|
3802
|
+
async function shutdown() {
|
|
3803
|
+
server.closeAllConnections?.();
|
|
3804
|
+
await Promise.all([
|
|
3805
|
+
new Promise((resolve) => listener?.close(resolve)),
|
|
3806
|
+
nitroApp.hooks.callHook("close").catch(console.error)
|
|
3807
|
+
]);
|
|
3808
|
+
parentPort?.postMessage({ event: "exit" });
|
|
3809
|
+
}
|
|
3810
|
+
|
|
3811
|
+
const _messages = {
|
|
3812
|
+
"appName": "Nuxt",
|
|
3813
|
+
"version": "",
|
|
3814
|
+
"status": 500,
|
|
3815
|
+
"statusText": "Server error",
|
|
3816
|
+
"description": "This page is temporarily unavailable."
|
|
3817
|
+
};
|
|
3818
|
+
const template$1 = (messages) => {
|
|
3819
|
+
messages = {
|
|
3820
|
+
..._messages,
|
|
3821
|
+
...messages
|
|
3822
|
+
};
|
|
3823
|
+
return "<!DOCTYPE html><html lang=\"en\"><head><title>" + escapeHtml(messages.status) + " - " + escapeHtml(messages.statusText) + " | " + escapeHtml(messages.appName) + "</title><meta charset=\"utf-8\"><meta content=\"width=device-width,initial-scale=1.0,minimum-scale=1.0\" name=\"viewport\"><style>.spotlight{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:\"\"}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}h1{font-size:inherit;font-weight:inherit}h1,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.fixed{position:fixed}.-bottom-1\\/2{bottom:-50%}.left-0{left:0}.right-0{right:0}.grid{display:grid}.mb-16{margin-bottom:4rem}.mb-8{margin-bottom:2rem}.h-1\\/2{height:50%}.max-w-520px{max-width:520px}.min-h-screen{min-height:100vh}.place-content-center{place-content:center}.overflow-hidden{overflow:hidden}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8{padding-left:2rem;padding-right:2rem}.text-center{text-align:center}.text-8xl{font-size:6rem;line-height:1}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-black{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light{font-weight:300}.font-medium{font-weight:500}.leading-tight{line-height:1.25}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media(prefers-color-scheme:dark){.dark\\:bg-black{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media(min-width:640px){.sm\\:px-0{padding-left:0;padding-right:0}.sm\\:text-4xl{font-size:2.25rem;line-height:2.5rem}}</style><script>!function(){const e=document.createElement(\"link\").relList;if(!(e&&e.supports&&e.supports(\"modulepreload\"))){for(const e of document.querySelectorAll('link[rel=\"modulepreload\"]'))r(e);new MutationObserver(e=>{for(const o of e)if(\"childList\"===o.type)for(const e of o.addedNodes)\"LINK\"===e.tagName&&\"modulepreload\"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),\"use-credentials\"===e.crossOrigin?r.credentials=\"include\":\"anonymous\"===e.crossOrigin?r.credentials=\"omit\":r.credentials=\"same-origin\",r}(e);fetch(e.href,r)}}();<\/script></head><body class=\"antialiased bg-white dark:bg-black dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-black\"><div class=\"-bottom-1/2 fixed h-1/2 left-0 right-0 spotlight\"></div><div class=\"max-w-520px text-center\"><h1 class=\"font-medium mb-8 sm:text-10xl text-8xl\">" + escapeHtml(messages.status) + "</h1><p class=\"font-light leading-tight mb-16 px-8 sm:px-0 sm:text-4xl text-xl\">" + escapeHtml(messages.description) + "</p></div></body></html>";
|
|
3824
|
+
};
|
|
3825
|
+
|
|
3826
|
+
const error500 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
3827
|
+
__proto__: null,
|
|
3828
|
+
template: template$1
|
|
3829
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
3830
|
+
|
|
3831
|
+
const template = "";
|
|
3832
|
+
|
|
3833
|
+
const _virtual__spaTemplate = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
3834
|
+
__proto__: null,
|
|
3835
|
+
template: template
|
|
3836
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
3837
|
+
|
|
3838
|
+
const styles = {};
|
|
3839
|
+
|
|
3840
|
+
const styles$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
3841
|
+
__proto__: null,
|
|
3842
|
+
default: styles
|
|
3843
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
3844
|
+
|
|
3845
|
+
function renderPayloadResponse(ssrContext) {
|
|
3846
|
+
return {
|
|
3847
|
+
body: stringify(splitPayload(ssrContext).payload, ssrContext["~payloadReducers"]) ,
|
|
3848
|
+
statusCode: getResponseStatus(ssrContext.event),
|
|
3849
|
+
statusMessage: getResponseStatusText(ssrContext.event),
|
|
3850
|
+
headers: {
|
|
3851
|
+
"content-type": "application/json;charset=utf-8" ,
|
|
3852
|
+
"x-powered-by": "Nuxt"
|
|
3853
|
+
}
|
|
3854
|
+
};
|
|
3855
|
+
}
|
|
3856
|
+
function renderPayloadJsonScript(opts) {
|
|
3857
|
+
const contents = opts.data ? stringify(opts.data, opts.ssrContext["~payloadReducers"]) : "";
|
|
3858
|
+
const payload = {
|
|
3859
|
+
"type": "application/json",
|
|
3860
|
+
"innerHTML": contents,
|
|
3861
|
+
"data-nuxt-data": appId,
|
|
3862
|
+
"data-ssr": !(opts.ssrContext.noSSR)
|
|
3863
|
+
};
|
|
3864
|
+
{
|
|
3865
|
+
payload.id = "__NUXT_DATA__";
|
|
3866
|
+
}
|
|
3867
|
+
if (opts.src) {
|
|
3868
|
+
payload["data-src"] = opts.src;
|
|
3869
|
+
}
|
|
3870
|
+
const config = uneval(opts.ssrContext.config);
|
|
3871
|
+
return [payload, { innerHTML: `window.__NUXT__={};window.__NUXT__.config=${config}` }];
|
|
3872
|
+
}
|
|
3873
|
+
function splitPayload(ssrContext) {
|
|
3874
|
+
const { data, prerenderedAt, ...initial } = ssrContext.payload;
|
|
3875
|
+
return {
|
|
3876
|
+
initial: {
|
|
3877
|
+
...initial,
|
|
3878
|
+
prerenderedAt
|
|
3879
|
+
},
|
|
3880
|
+
payload: {
|
|
3881
|
+
data,
|
|
3882
|
+
prerenderedAt
|
|
3883
|
+
}
|
|
3884
|
+
};
|
|
3885
|
+
}
|
|
3886
|
+
|
|
3887
|
+
const renderSSRHeadOptions = {"omitLineBreaks":false};
|
|
3888
|
+
|
|
3889
|
+
// @ts-expect-error private property consumed by vite-generated url helpers
|
|
3890
|
+
globalThis.__buildAssetsURL = buildAssetsURL;
|
|
3891
|
+
// @ts-expect-error private property consumed by vite-generated url helpers
|
|
3892
|
+
globalThis.__publicAssetsURL = publicAssetsURL;
|
|
3893
|
+
const HAS_APP_TELEPORTS = !!(appTeleportAttrs.id);
|
|
3894
|
+
const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : "";
|
|
3895
|
+
const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : "";
|
|
3896
|
+
const PAYLOAD_URL_RE = /^[^?]*\/_payload.json(?:\?.*)?$/ ;
|
|
3897
|
+
const PAYLOAD_FILENAME = "_payload.json" ;
|
|
3898
|
+
const renderer = defineRenderHandler(async (event) => {
|
|
3899
|
+
const nitroApp = useNitroApp();
|
|
3900
|
+
// Whether we're rendering an error page
|
|
3901
|
+
const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery$1(event) : null;
|
|
3902
|
+
if (ssrError && !("__unenv__" in event.node.req)) {
|
|
3903
|
+
throw createError({
|
|
3904
|
+
status: 404,
|
|
3905
|
+
statusText: "Page Not Found: /__nuxt_error",
|
|
3906
|
+
message: "Page Not Found: /__nuxt_error"
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
// Initialize ssr context
|
|
3910
|
+
const ssrContext = createSSRContext(event);
|
|
3911
|
+
// needed for hash hydration plugin to work
|
|
3912
|
+
const headEntryOptions = { mode: "server" };
|
|
3913
|
+
ssrContext.head.push(appHead, headEntryOptions);
|
|
3914
|
+
if (ssrError) {
|
|
3915
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
3916
|
+
const status = ssrError.status || ssrError.statusCode;
|
|
3917
|
+
if (status) {
|
|
3918
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
3919
|
+
ssrError.status = ssrError.statusCode = Number.parseInt(status);
|
|
3920
|
+
}
|
|
3921
|
+
setSSRError(ssrContext, ssrError);
|
|
3922
|
+
}
|
|
3923
|
+
// Get route options (for `ssr: false`, `isr`, `cache` and `noScripts`)
|
|
3924
|
+
const routeOptions = getRouteRules(event);
|
|
3925
|
+
// Whether we are prerendering route or using ISR/SWR caching
|
|
3926
|
+
const _PAYLOAD_EXTRACTION = !ssrContext.noSSR && (NUXT_RUNTIME_PAYLOAD_EXTRACTION);
|
|
3927
|
+
const isRenderingPayload = (_PAYLOAD_EXTRACTION || routeOptions.prerender) && PAYLOAD_URL_RE.test(ssrContext.url);
|
|
3928
|
+
if (isRenderingPayload) {
|
|
3929
|
+
const url = ssrContext.url.substring(0, ssrContext.url.lastIndexOf("/")) || "/";
|
|
3930
|
+
ssrContext.url = url;
|
|
3931
|
+
event._path = event.node.req.url = url;
|
|
3932
|
+
}
|
|
3933
|
+
if (routeOptions.ssr === false) {
|
|
3934
|
+
ssrContext.noSSR = true;
|
|
3935
|
+
}
|
|
3936
|
+
const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(ssrContext.runtimeConfig.app.cdnURL || ssrContext.runtimeConfig.app.baseURL, ssrContext.url.replace(/\?.*$/, ""), PAYLOAD_FILENAME) + "?" + ssrContext.runtimeConfig.app.buildId : undefined;
|
|
3937
|
+
// Render app
|
|
3938
|
+
const renderer = await getRenderer(ssrContext);
|
|
3939
|
+
const _rendered = await renderer.renderToString(ssrContext).catch(async (error) => {
|
|
3940
|
+
// We use error to bypass full render if we have an early response we can make
|
|
3941
|
+
// TODO: remove _renderResponse in nuxt v5
|
|
3942
|
+
if ((ssrContext["~renderResponse"] || ssrContext._renderResponse) && error.message === "skipping render") {
|
|
3943
|
+
return {};
|
|
3944
|
+
}
|
|
3945
|
+
// Use explicitly thrown error in preference to subsequent rendering errors
|
|
3946
|
+
const _err = !ssrError && ssrContext.payload?.error || error;
|
|
3947
|
+
await ssrContext.nuxt?.hooks.callHook("app:error", _err);
|
|
3948
|
+
throw _err;
|
|
3949
|
+
});
|
|
3950
|
+
// Render inline styles
|
|
3951
|
+
// TODO: remove _renderResponse in nuxt v5
|
|
3952
|
+
const inlinedStyles = [];
|
|
3953
|
+
await ssrContext.nuxt?.hooks.callHook("app:rendered", {
|
|
3954
|
+
ssrContext,
|
|
3955
|
+
renderResult: _rendered
|
|
3956
|
+
});
|
|
3957
|
+
if (ssrContext["~renderResponse"] || ssrContext._renderResponse) {
|
|
3958
|
+
// TODO: remove _renderResponse in nuxt v5
|
|
3959
|
+
return ssrContext["~renderResponse"] || ssrContext._renderResponse;
|
|
3960
|
+
}
|
|
3961
|
+
// Handle errors
|
|
3962
|
+
if (ssrContext.payload?.error && !ssrError) {
|
|
3963
|
+
throw ssrContext.payload.error;
|
|
3964
|
+
}
|
|
3965
|
+
// Directly render payload routes
|
|
3966
|
+
if (isRenderingPayload) {
|
|
3967
|
+
const response = renderPayloadResponse(ssrContext);
|
|
3968
|
+
return response;
|
|
3969
|
+
}
|
|
3970
|
+
const NO_SCRIPTS = routeOptions.noScripts;
|
|
3971
|
+
// Setup head
|
|
3972
|
+
const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext);
|
|
3973
|
+
// 1. Preload payloads and app manifest
|
|
3974
|
+
if (_PAYLOAD_EXTRACTION && !NO_SCRIPTS) {
|
|
3975
|
+
ssrContext.head.push({ link: [{
|
|
3976
|
+
rel: "preload",
|
|
3977
|
+
as: "fetch",
|
|
3978
|
+
crossorigin: "anonymous",
|
|
3979
|
+
href: payloadURL
|
|
3980
|
+
} ] }, headEntryOptions);
|
|
3981
|
+
}
|
|
3982
|
+
if (ssrContext["~preloadManifest"] && !NO_SCRIPTS) {
|
|
3983
|
+
ssrContext.head.push({ link: [{
|
|
3984
|
+
rel: "preload",
|
|
3985
|
+
as: "fetch",
|
|
3986
|
+
fetchpriority: "low",
|
|
3987
|
+
crossorigin: "anonymous",
|
|
3988
|
+
href: buildAssetsURL(`builds/meta/${ssrContext.runtimeConfig.app.buildId}.json`)
|
|
3989
|
+
}] }, {
|
|
3990
|
+
...headEntryOptions,
|
|
3991
|
+
tagPriority: "low"
|
|
3992
|
+
});
|
|
3993
|
+
}
|
|
3994
|
+
// 2. Styles
|
|
3995
|
+
if (inlinedStyles.length) {
|
|
3996
|
+
ssrContext.head.push({ style: inlinedStyles });
|
|
3997
|
+
}
|
|
3998
|
+
const link = [];
|
|
3999
|
+
for (const resource of Object.values(styles)) {
|
|
4000
|
+
// Do not add links to resources that are inlined (vite v5+)
|
|
4001
|
+
if ("inline" in getQuery(resource.file)) {
|
|
4002
|
+
continue;
|
|
4003
|
+
}
|
|
4004
|
+
// Add CSS links in <head> for CSS files
|
|
4005
|
+
// - in production
|
|
4006
|
+
// - in dev mode when not rendering an island
|
|
4007
|
+
link.push({
|
|
4008
|
+
rel: "stylesheet",
|
|
4009
|
+
href: renderer.rendererContext.buildAssetsURL(resource.file),
|
|
4010
|
+
crossorigin: ""
|
|
4011
|
+
});
|
|
4012
|
+
}
|
|
4013
|
+
if (link.length) {
|
|
4014
|
+
ssrContext.head.push({ link }, headEntryOptions);
|
|
4015
|
+
}
|
|
4016
|
+
if (!NO_SCRIPTS) {
|
|
4017
|
+
// 4. Resource Hints
|
|
4018
|
+
// Remove lazy hydrated modules from ssrContext.modules so they don't get preloaded
|
|
4019
|
+
// (CSS links are already added above, this only affects JS preloads)
|
|
4020
|
+
if (ssrContext["~lazyHydratedModules"]) {
|
|
4021
|
+
for (const id of ssrContext["~lazyHydratedModules"]) {
|
|
4022
|
+
ssrContext.modules?.delete(id);
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
// TODO: add priorities based on Capo
|
|
4026
|
+
ssrContext.head.push({ link: getPreloadLinks(ssrContext, renderer.rendererContext) }, headEntryOptions);
|
|
4027
|
+
ssrContext.head.push({ link: getPrefetchLinks(ssrContext, renderer.rendererContext) }, headEntryOptions);
|
|
4028
|
+
// 5. Payloads
|
|
4029
|
+
ssrContext.head.push({ script: _PAYLOAD_EXTRACTION ? renderPayloadJsonScript({
|
|
4030
|
+
ssrContext,
|
|
4031
|
+
data: splitPayload(ssrContext).initial,
|
|
4032
|
+
src: payloadURL
|
|
4033
|
+
}) : renderPayloadJsonScript({
|
|
4034
|
+
ssrContext,
|
|
4035
|
+
data: ssrContext.payload
|
|
4036
|
+
}) }, {
|
|
4037
|
+
...headEntryOptions,
|
|
4038
|
+
tagPosition: "bodyClose",
|
|
4039
|
+
tagPriority: "high"
|
|
4040
|
+
});
|
|
4041
|
+
}
|
|
4042
|
+
// 6. Scripts
|
|
4043
|
+
if (!routeOptions.noScripts) {
|
|
4044
|
+
const tagPosition = "head";
|
|
4045
|
+
ssrContext.head.push({ script: Object.values(scripts).map((resource) => ({
|
|
4046
|
+
type: resource.module ? "module" : null,
|
|
4047
|
+
src: renderer.rendererContext.buildAssetsURL(resource.file),
|
|
4048
|
+
defer: resource.module ? null : true,
|
|
4049
|
+
tagPosition,
|
|
4050
|
+
crossorigin: ""
|
|
4051
|
+
})) }, headEntryOptions);
|
|
4052
|
+
}
|
|
4053
|
+
const { headTags, bodyTags, bodyTagsOpen, htmlAttrs, bodyAttrs } = await renderSSRHead(ssrContext.head, renderSSRHeadOptions);
|
|
4054
|
+
// Create render context
|
|
4055
|
+
const htmlContext = {
|
|
4056
|
+
htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
|
|
4057
|
+
head: normalizeChunks([headTags]),
|
|
4058
|
+
bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
|
|
4059
|
+
bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
|
|
4060
|
+
body: [replaceIslandTeleports(ssrContext, _rendered.html) , APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportAttrs.id}`]]) : "") + APP_TELEPORT_CLOSE_TAG],
|
|
4061
|
+
bodyAppend: [bodyTags]
|
|
4062
|
+
};
|
|
4063
|
+
// Allow hooking into the rendered result
|
|
4064
|
+
await nitroApp.hooks.callHook("render:html", htmlContext, { event });
|
|
4065
|
+
// Construct HTML response
|
|
4066
|
+
return {
|
|
4067
|
+
body: renderHTMLDocument(htmlContext),
|
|
4068
|
+
statusCode: getResponseStatus(event),
|
|
4069
|
+
statusMessage: getResponseStatusText(event),
|
|
4070
|
+
headers: {
|
|
4071
|
+
"content-type": "text/html;charset=utf-8",
|
|
4072
|
+
"x-powered-by": "Nuxt"
|
|
4073
|
+
}
|
|
4074
|
+
};
|
|
4075
|
+
});
|
|
4076
|
+
function normalizeChunks(chunks) {
|
|
4077
|
+
const result = [];
|
|
4078
|
+
for (const _chunk of chunks) {
|
|
4079
|
+
const chunk = _chunk?.trim();
|
|
4080
|
+
if (chunk) {
|
|
4081
|
+
result.push(chunk);
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
return result;
|
|
4085
|
+
}
|
|
4086
|
+
function joinTags(tags) {
|
|
4087
|
+
return tags.join("");
|
|
4088
|
+
}
|
|
4089
|
+
function joinAttrs(chunks) {
|
|
4090
|
+
if (chunks.length === 0) {
|
|
4091
|
+
return "";
|
|
4092
|
+
}
|
|
4093
|
+
return " " + chunks.join(" ");
|
|
4094
|
+
}
|
|
4095
|
+
function renderHTMLDocument(html) {
|
|
4096
|
+
return "<!DOCTYPE html>" + `<html${joinAttrs(html.htmlAttrs)}>` + `<head>${joinTags(html.head)}</head>` + `<body${joinAttrs(html.bodyAttrs)}>${joinTags(html.bodyPrepend)}${joinTags(html.body)}${joinTags(html.bodyAppend)}</body>` + "</html>";
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
const renderer$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
4100
|
+
__proto__: null,
|
|
4101
|
+
default: renderer
|
|
4102
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
4103
|
+
//# sourceMappingURL=index.mjs.map
|