@nuxt/nitro-server-nightly 4.3.0-29461891.8f4fbecd → 4.3.0-29466366.fa21bb17

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.
Files changed (63) hide show
  1. package/dist/index.d.mts +178 -80
  2. package/dist/index.mjs +664 -810
  3. package/dist/runtime/handlers/{error.d.ts → error.d.mts} +1 -1
  4. package/dist/runtime/handlers/error.mjs +77 -0
  5. package/dist/runtime/handlers/island.d.mts +2 -0
  6. package/dist/runtime/handlers/island.mjs +120 -0
  7. package/dist/runtime/handlers/renderer.d.mts +2 -0
  8. package/dist/runtime/handlers/renderer.mjs +298 -0
  9. package/dist/runtime/middleware/no-ssr.d.mts +2 -0
  10. package/dist/runtime/middleware/no-ssr.mjs +7 -0
  11. package/dist/runtime/plugins/dev-server-logs.d.mts +2 -0
  12. package/dist/runtime/plugins/dev-server-logs.mjs +94 -0
  13. package/dist/runtime/templates/error-500.mjs +15 -0
  14. package/dist/runtime/utils/app-config.d.mts +3 -0
  15. package/dist/runtime/utils/app-config.mjs +31 -0
  16. package/dist/runtime/utils/cache.d.mts +5 -0
  17. package/dist/runtime/utils/{cache.js → cache.mjs} +13 -12
  18. package/dist/runtime/utils/config.d.mts +1 -0
  19. package/dist/runtime/utils/{dev.d.ts → dev.d.mts} +1 -1
  20. package/dist/runtime/utils/{dev.js → dev.mjs} +15 -27
  21. package/dist/runtime/utils/error.d.mts +6 -0
  22. package/dist/runtime/utils/error.mjs +15 -0
  23. package/dist/runtime/utils/paths.mjs +19 -0
  24. package/dist/runtime/utils/renderer/{app.d.ts → app.d.mts} +4 -4
  25. package/dist/runtime/utils/renderer/app.mjs +39 -0
  26. package/dist/runtime/utils/renderer/build-files.d.mts +18 -0
  27. package/dist/runtime/utils/renderer/build-files.mjs +100 -0
  28. package/dist/runtime/utils/renderer/{inline-styles.d.ts → inline-styles.d.mts} +1 -1
  29. package/dist/runtime/utils/renderer/inline-styles.mjs +13 -0
  30. package/dist/runtime/utils/renderer/{islands.d.ts → islands.d.mts} +5 -5
  31. package/dist/runtime/utils/renderer/islands.mjs +87 -0
  32. package/dist/runtime/utils/renderer/payload.d.mts +24 -0
  33. package/dist/runtime/utils/renderer/payload.mjs +64 -0
  34. package/package.json +8 -8
  35. package/dist/index.d.ts +0 -87
  36. package/dist/runtime/handlers/error.js +0 -65
  37. package/dist/runtime/handlers/island.d.ts +0 -4
  38. package/dist/runtime/handlers/island.js +0 -101
  39. package/dist/runtime/handlers/renderer.d.ts +0 -2
  40. package/dist/runtime/handlers/renderer.js +0 -237
  41. package/dist/runtime/middleware/no-ssr.d.ts +0 -2
  42. package/dist/runtime/middleware/no-ssr.js +0 -7
  43. package/dist/runtime/plugins/dev-server-logs.d.ts +0 -3
  44. package/dist/runtime/plugins/dev-server-logs.js +0 -82
  45. package/dist/runtime/templates/error-500.js +0 -6
  46. package/dist/runtime/utils/app-config.d.ts +0 -3
  47. package/dist/runtime/utils/app-config.js +0 -25
  48. package/dist/runtime/utils/cache-driver.d.ts +0 -6
  49. package/dist/runtime/utils/cache.d.ts +0 -8
  50. package/dist/runtime/utils/config.d.ts +0 -1
  51. package/dist/runtime/utils/error.d.ts +0 -6
  52. package/dist/runtime/utils/error.js +0 -11
  53. package/dist/runtime/utils/paths.js +0 -16
  54. package/dist/runtime/utils/renderer/app.js +0 -34
  55. package/dist/runtime/utils/renderer/build-files.d.ts +0 -16
  56. package/dist/runtime/utils/renderer/build-files.js +0 -86
  57. package/dist/runtime/utils/renderer/inline-styles.js +0 -13
  58. package/dist/runtime/utils/renderer/islands.js +0 -82
  59. package/dist/runtime/utils/renderer/payload.d.ts +0 -24
  60. package/dist/runtime/utils/renderer/payload.js +0 -67
  61. /package/dist/runtime/templates/{error-500.d.ts → error-500.d.mts} +0 -0
  62. /package/dist/runtime/utils/{config.js → config.mjs} +0 -0
  63. /package/dist/runtime/utils/{paths.d.ts → paths.d.mts} +0 -0
@@ -1,3 +1,3 @@
1
- import type { NitroErrorHandler } from 'nitropack/types';
1
+ import type { NitroErrorHandler } from "nitropack/types";
2
2
  declare const _default: NitroErrorHandler;
3
3
  export default _default;
@@ -0,0 +1,77 @@
1
+ import { joinURL, withQuery, withoutBase } from "ufo";
2
+ import { appendResponseHeader, getRequestHeaders, send, setResponseHeader, setResponseHeaders, setResponseStatus } from "h3";
3
+ import { useNitroApp, useRuntimeConfig } from "nitropack/runtime";
4
+ import { isJsonRequest } from "../utils/error.mjs";
5
+ import { generateErrorOverlayHTML } from "../utils/dev.mjs";
6
+ export default (async function errorhandler(error, event, { defaultHandler }) {
7
+ if (event.handled || isJsonRequest(event)) {
8
+ // let Nitro handle JSON errors
9
+ return;
10
+ }
11
+ // invoke default Nitro error handler (which will log appropriately if required)
12
+ const defaultRes = await defaultHandler(error, event, { json: true });
13
+ // let Nitro handle redirect if appropriate
14
+ const status = error.status || error.statusCode || 500;
15
+ if (status === 404 && defaultRes.status === 302) {
16
+ setResponseHeaders(event, defaultRes.headers);
17
+ setResponseStatus(event, defaultRes.status, defaultRes.statusText);
18
+ return send(event, JSON.stringify(defaultRes.body, null, 2));
19
+ }
20
+ if (import.meta.dev && typeof defaultRes.body !== "string" && Array.isArray(defaultRes.body.stack)) {
21
+ // normalize to string format expected by nuxt `error.vue`
22
+ defaultRes.body.stack = defaultRes.body.stack.join("\n");
23
+ }
24
+ const errorObject = defaultRes.body;
25
+ // remove proto/hostname/port from URL
26
+ const url = new URL(errorObject.url);
27
+ errorObject.url = withoutBase(url.pathname, useRuntimeConfig(event).app.baseURL) + url.search + url.hash;
28
+ // add default server message
29
+ errorObject.message ||= "Server Error";
30
+ // we will be rendering this error internally so we can pass along the error.data safely
31
+ errorObject.data ||= error.data;
32
+ errorObject.statusText ||= error.statusText || error.statusMessage;
33
+ delete defaultRes.headers["content-type"];
34
+ delete defaultRes.headers["content-security-policy"];
35
+ setResponseHeaders(event, defaultRes.headers);
36
+ // Access request headers
37
+ const reqHeaders = getRequestHeaders(event);
38
+ // Detect to avoid recursion in SSR rendering of errors
39
+ const isRenderingError = event.path.startsWith("/__nuxt_error") || !!reqHeaders["x-nuxt-error"];
40
+ // HTML response (via SSR)
41
+ const res = isRenderingError ? null : await useNitroApp().localFetch(withQuery(joinURL(useRuntimeConfig(event).app.baseURL, "/__nuxt_error"), errorObject), {
42
+ headers: {
43
+ ...reqHeaders,
44
+ "x-nuxt-error": "true"
45
+ },
46
+ redirect: "manual"
47
+ }).catch(() => null);
48
+ if (event.handled) {
49
+ return;
50
+ }
51
+ // Fallback to static rendered error page
52
+ if (!res) {
53
+ const { template } = await import("../templates/error-500");
54
+ if (import.meta.dev) {
55
+ // TODO: Support `message` in template
56
+ errorObject.description = errorObject.message;
57
+ }
58
+ setResponseHeader(event, "Content-Type", "text/html;charset=UTF-8");
59
+ return send(event, template(errorObject));
60
+ }
61
+ const html = await res.text();
62
+ for (const [header, value] of res.headers.entries()) {
63
+ if (header === "set-cookie") {
64
+ appendResponseHeader(event, header, value);
65
+ continue;
66
+ }
67
+ setResponseHeader(event, header, value);
68
+ }
69
+ setResponseStatus(event, res.status && res.status !== 200 ? res.status : defaultRes.status, res.statusText || defaultRes.statusText);
70
+ if (import.meta.dev && !import.meta.test && typeof html === "string") {
71
+ const prettyResponse = await defaultHandler(error, event, { json: false });
72
+ if (typeof prettyResponse.body === "string") {
73
+ return send(event, html.replace("</body>", `${generateErrorOverlayHTML(prettyResponse.body, { startMinimized: 300 <= status && status < 500 })}</body>`));
74
+ }
75
+ }
76
+ return send(event, html);
77
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default;
2
+ export default _default;
@@ -0,0 +1,120 @@
1
+ import { useNitroApp } from "nitropack/runtime";
2
+ import { destr } from "destr";
3
+ import { defineEventHandler, getQuery, readBody, setResponseHeaders } from "h3";
4
+ import { resolveUnrefHeadInput } from "@unhead/vue";
5
+ import { getRequestDependencies } from "vue-bundle-renderer/runtime";
6
+ import { getQuery as getURLQuery } from "ufo";
7
+ import { islandCache, islandPropCache } from "../utils/cache.mjs";
8
+ import { createSSRContext } from "../utils/renderer/app.mjs";
9
+ import { getSSRRenderer } from "../utils/renderer/build-files.mjs";
10
+ import { renderInlineStyles } from "../utils/renderer/inline-styles.mjs";
11
+ import { getClientIslandResponse, getServerComponentHTML, getSlotIslandResponse } from "../utils/renderer/islands.mjs";
12
+ const ISLAND_SUFFIX_RE = /\.json(?:\?.*)?$/;
13
+ export default defineEventHandler(async (event) => {
14
+ const nitroApp = useNitroApp();
15
+ setResponseHeaders(event, {
16
+ "content-type": "application/json;charset=utf-8",
17
+ "x-powered-by": "Nuxt"
18
+ });
19
+ if (import.meta.prerender && event.path && await islandCache.hasItem(event.path)) {
20
+ return islandCache.getItem(event.path);
21
+ }
22
+ const islandContext = await getIslandContext(event);
23
+ const ssrContext = {
24
+ ...createSSRContext(event),
25
+ islandContext,
26
+ noSSR: false,
27
+ url: islandContext.url
28
+ };
29
+ // Render app
30
+ const renderer = await getSSRRenderer();
31
+ const renderResult = await renderer.renderToString(ssrContext).catch(async (err) => {
32
+ await ssrContext.nuxt?.hooks.callHook("app:error", err);
33
+ throw err;
34
+ });
35
+ // Handle errors
36
+ if (ssrContext.payload?.error) {
37
+ throw ssrContext.payload.error;
38
+ }
39
+ const inlinedStyles = await renderInlineStyles(ssrContext.modules ?? []);
40
+ await ssrContext.nuxt?.hooks.callHook("app:rendered", {
41
+ ssrContext,
42
+ renderResult
43
+ });
44
+ if (inlinedStyles.length) {
45
+ ssrContext.head.push({ style: inlinedStyles });
46
+ }
47
+ if (import.meta.dev) {
48
+ const { styles } = getRequestDependencies(ssrContext, renderer.rendererContext);
49
+ const link = [];
50
+ for (const resource of Object.values(styles)) {
51
+ // Do not add links to resources that are inlined (vite v5+)
52
+ if ("inline" in getURLQuery(resource.file)) {
53
+ continue;
54
+ }
55
+ // Add CSS links in <head> for CSS files
56
+ // - in dev mode when rendering an island and the file has scoped styles and is not a page
57
+ if (resource.file.includes("scoped") && !resource.file.includes("pages/")) {
58
+ link.push({
59
+ rel: "stylesheet",
60
+ href: renderer.rendererContext.buildAssetsURL(resource.file),
61
+ crossorigin: ""
62
+ });
63
+ }
64
+ }
65
+ if (link.length) {
66
+ ssrContext.head.push({ link }, { mode: "server" });
67
+ }
68
+ }
69
+ const islandHead = {};
70
+ for (const entry of ssrContext.head.entries.values()) {
71
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
72
+ for (const [key, value] of Object.entries(resolveUnrefHeadInput(entry.input))) {
73
+ const currentValue = islandHead[key];
74
+ if (Array.isArray(currentValue)) {
75
+ currentValue.push(...value);
76
+ } else {
77
+ islandHead[key] = value;
78
+ }
79
+ }
80
+ }
81
+ const islandResponse = {
82
+ id: islandContext.id,
83
+ head: islandHead,
84
+ html: getServerComponentHTML(renderResult.html),
85
+ components: getClientIslandResponse(ssrContext),
86
+ slots: getSlotIslandResponse(ssrContext)
87
+ };
88
+ await nitroApp.hooks.callHook("render:island", islandResponse, {
89
+ event,
90
+ islandContext
91
+ });
92
+ if (import.meta.prerender) {
93
+ await islandCache.setItem(`/__nuxt_island/${islandContext.name}_${islandContext.id}.json`, islandResponse);
94
+ await islandPropCache.setItem(`/__nuxt_island/${islandContext.name}_${islandContext.id}.json`, event.path);
95
+ }
96
+ return islandResponse;
97
+ });
98
+ async function getIslandContext(event) {
99
+ // TODO: Strict validation for url
100
+ let url = event.path || "";
101
+ if (import.meta.prerender && event.path && await islandPropCache.hasItem(event.path)) {
102
+ // rehydrate props from cache so we can rerender island if cache does not have it any more
103
+ url = await islandPropCache.getItem(event.path);
104
+ }
105
+ const componentParts = url.substring("/__nuxt_island".length + 1).replace(ISLAND_SUFFIX_RE, "").split("_");
106
+ const hashId = componentParts.length > 1 ? componentParts.pop() : undefined;
107
+ const componentName = componentParts.join("_");
108
+ // TODO: Validate context
109
+ const context = event.method === "GET" ? getQuery(event) : await readBody(event);
110
+ const ctx = {
111
+ url: "/",
112
+ ...context,
113
+ id: hashId,
114
+ name: componentName,
115
+ props: destr(context.props) || {},
116
+ slots: {},
117
+ components: {}
118
+ };
119
+ return ctx;
120
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default;
2
+ export default _default;
@@ -0,0 +1,298 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { getPrefetchLinks, getPreloadLinks, getRequestDependencies, renderResourceHeaders } from "vue-bundle-renderer/runtime";
3
+ import { appendResponseHeader, createError, getQuery, getResponseStatus, getResponseStatusText, writeEarlyHints } from "h3";
4
+ import { getQuery as getURLQuery, joinURL } from "ufo";
5
+ import { propsToString, renderSSRHead } from "@unhead/vue/server";
6
+ import destr from "destr";
7
+ import { defineRenderHandler, getRouteRules, useNitroApp } from "nitropack/runtime";
8
+ import { getRenderer } from "../utils/renderer/build-files.mjs";
9
+ import { payloadCache } from "../utils/cache.mjs";
10
+ import { renderPayloadJsonScript, renderPayloadResponse, renderPayloadScript, splitPayload } from "../utils/renderer/payload.mjs";
11
+ import { createSSRContext, setSSRError } from "../utils/renderer/app.mjs";
12
+ import { renderInlineStyles } from "../utils/renderer/inline-styles.mjs";
13
+ import { replaceIslandTeleports } from "../utils/renderer/islands.mjs";
14
+ // @ts-expect-error virtual file
15
+ import { renderSSRHeadOptions } from "#internal/unhead.config.mjs";
16
+ // @ts-expect-error virtual file
17
+ import { NUXT_ASYNC_CONTEXT, NUXT_EARLY_HINTS, NUXT_INLINE_STYLES, NUXT_JSON_PAYLOADS, NUXT_NO_SCRIPTS, NUXT_PAYLOAD_EXTRACTION, NUXT_RUNTIME_PAYLOAD_EXTRACTION, PARSE_ERROR_DATA } from "#internal/nuxt/nitro-config.mjs";
18
+ // @ts-expect-error virtual file
19
+ import { appHead, appTeleportAttrs, appTeleportTag, componentIslands, appManifest as isAppManifestEnabled } from "#internal/nuxt.config.mjs";
20
+ // @ts-expect-error virtual file
21
+ import entryIds from "#internal/nuxt/entry-ids.mjs";
22
+ // @ts-expect-error virtual file
23
+ import { entryFileName } from "#internal/entry-chunk.mjs";
24
+ // @ts-expect-error virtual file
25
+ import { buildAssetsURL, publicAssetsURL } from "#internal/nuxt/paths";
26
+ import { relative } from "pathe";
27
+ // @ts-expect-error private property consumed by vite-generated url helpers
28
+ globalThis.__buildAssetsURL = buildAssetsURL;
29
+ // @ts-expect-error private property consumed by vite-generated url helpers
30
+ globalThis.__publicAssetsURL = publicAssetsURL;
31
+ // Polyfill for unctx (https://github.com/unjs/unctx#native-async-context)
32
+ if (NUXT_ASYNC_CONTEXT && !("AsyncLocalStorage" in globalThis)) {
33
+ globalThis.AsyncLocalStorage = AsyncLocalStorage;
34
+ }
35
+ const HAS_APP_TELEPORTS = !!(appTeleportTag && appTeleportAttrs.id);
36
+ const APP_TELEPORT_OPEN_TAG = HAS_APP_TELEPORTS ? `<${appTeleportTag}${propsToString(appTeleportAttrs)}>` : "";
37
+ const APP_TELEPORT_CLOSE_TAG = HAS_APP_TELEPORTS ? `</${appTeleportTag}>` : "";
38
+ const PAYLOAD_URL_RE = NUXT_JSON_PAYLOADS ? /^[^?]*\/_payload.json(?:\?.*)?$/ : /^[^?]*\/_payload.js(?:\?.*)?$/;
39
+ const PAYLOAD_FILENAME = NUXT_JSON_PAYLOADS ? "_payload.json" : "_payload.js";
40
+ let entryPath;
41
+ export default defineRenderHandler(async (event) => {
42
+ const nitroApp = useNitroApp();
43
+ // Whether we're rendering an error page
44
+ const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery(event) : null;
45
+ if (ssrError && !("__unenv__" in event.node.req)) {
46
+ throw createError({
47
+ status: 404,
48
+ statusText: "Page Not Found: /__nuxt_error",
49
+ message: "Page Not Found: /__nuxt_error"
50
+ });
51
+ }
52
+ // Initialize ssr context
53
+ const ssrContext = createSSRContext(event);
54
+ // needed for hash hydration plugin to work
55
+ const headEntryOptions = { mode: "server" };
56
+ ssrContext.head.push(appHead, headEntryOptions);
57
+ if (ssrError) {
58
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
59
+ const status = ssrError.status || ssrError.statusCode;
60
+ if (status) {
61
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
62
+ ssrError.status = ssrError.statusCode = Number.parseInt(status);
63
+ }
64
+ if (PARSE_ERROR_DATA && typeof ssrError.data === "string") {
65
+ try {
66
+ ssrError.data = destr(ssrError.data);
67
+ } catch {}
68
+ }
69
+ setSSRError(ssrContext, ssrError);
70
+ }
71
+ // Get route options (for `ssr: false`, `isr`, `cache` and `noScripts`)
72
+ const routeOptions = getRouteRules(event);
73
+ // Whether we are prerendering route or using ISR/SWR caching
74
+ const _PAYLOAD_EXTRACTION = !ssrContext.noSSR && (import.meta.prerender && NUXT_PAYLOAD_EXTRACTION || NUXT_RUNTIME_PAYLOAD_EXTRACTION && (routeOptions.isr || routeOptions.cache));
75
+ const isRenderingPayload = (_PAYLOAD_EXTRACTION || import.meta.dev && routeOptions.prerender) && PAYLOAD_URL_RE.test(ssrContext.url);
76
+ if (isRenderingPayload) {
77
+ const url = ssrContext.url.substring(0, ssrContext.url.lastIndexOf("/")) || "/";
78
+ ssrContext.url = url;
79
+ event._path = event.node.req.url = url;
80
+ if (import.meta.prerender && await payloadCache.hasItem(url)) {
81
+ return payloadCache.getItem(url);
82
+ }
83
+ }
84
+ if (routeOptions.ssr === false) {
85
+ ssrContext.noSSR = true;
86
+ }
87
+ const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(ssrContext.runtimeConfig.app.cdnURL || ssrContext.runtimeConfig.app.baseURL, ssrContext.url.replace(/\?.*$/, ""), PAYLOAD_FILENAME) + "?" + ssrContext.runtimeConfig.app.buildId : undefined;
88
+ // Render app
89
+ const renderer = await getRenderer(ssrContext);
90
+ // Render 103 Early Hints
91
+ if (NUXT_EARLY_HINTS && !isRenderingPayload && !import.meta.prerender) {
92
+ const { link } = renderResourceHeaders({}, renderer.rendererContext);
93
+ if (link) {
94
+ writeEarlyHints(event, link);
95
+ }
96
+ }
97
+ if (NUXT_INLINE_STYLES) {
98
+ for (const id of entryIds) {
99
+ ssrContext.modules.add(id);
100
+ }
101
+ }
102
+ const _rendered = await renderer.renderToString(ssrContext).catch(async (error) => {
103
+ // We use error to bypass full render if we have an early response we can make
104
+ // TODO: remove _renderResponse in nuxt v5
105
+ if ((ssrContext["~renderResponse"] || ssrContext._renderResponse) && error.message === "skipping render") {
106
+ return {};
107
+ }
108
+ // Use explicitly thrown error in preference to subsequent rendering errors
109
+ const _err = !ssrError && ssrContext.payload?.error || error;
110
+ await ssrContext.nuxt?.hooks.callHook("app:error", _err);
111
+ throw _err;
112
+ });
113
+ // Render inline styles
114
+ // TODO: remove _renderResponse in nuxt v5
115
+ const inlinedStyles = NUXT_INLINE_STYLES && !ssrContext["~renderResponse"] && !ssrContext._renderResponse && !isRenderingPayload ? await renderInlineStyles(ssrContext.modules ?? []) : [];
116
+ await ssrContext.nuxt?.hooks.callHook("app:rendered", {
117
+ ssrContext,
118
+ renderResult: _rendered
119
+ });
120
+ if (ssrContext["~renderResponse"] || ssrContext._renderResponse) {
121
+ // TODO: remove _renderResponse in nuxt v5
122
+ return ssrContext["~renderResponse"] || ssrContext._renderResponse;
123
+ }
124
+ // Handle errors
125
+ if (ssrContext.payload?.error && !ssrError) {
126
+ throw ssrContext.payload.error;
127
+ }
128
+ // Directly render payload routes
129
+ if (isRenderingPayload) {
130
+ const response = renderPayloadResponse(ssrContext);
131
+ if (import.meta.prerender) {
132
+ await payloadCache.setItem(ssrContext.url, response);
133
+ }
134
+ return response;
135
+ }
136
+ if (_PAYLOAD_EXTRACTION && import.meta.prerender) {
137
+ // Hint nitro to prerender payload for this route
138
+ appendResponseHeader(event, "x-nitro-prerender", joinURL(ssrContext.url.replace(/\?.*$/, ""), PAYLOAD_FILENAME));
139
+ // Use same ssr context to generate payload for this route
140
+ await payloadCache.setItem(ssrContext.url === "/" ? "/" : ssrContext.url.replace(/\/$/, ""), renderPayloadResponse(ssrContext));
141
+ }
142
+ const NO_SCRIPTS = NUXT_NO_SCRIPTS || routeOptions.noScripts;
143
+ // Setup head
144
+ const { styles, scripts } = getRequestDependencies(ssrContext, renderer.rendererContext);
145
+ // 0. Add import map for stable chunk hashes
146
+ if (entryFileName && !NO_SCRIPTS) {
147
+ let path = entryPath;
148
+ if (!path) {
149
+ path = buildAssetsURL(entryFileName);
150
+ if (ssrContext.runtimeConfig.app.cdnURL || /^(?:\/|\.+\/)/.test(path)) {
151
+ // cache absolute entry path
152
+ entryPath = path;
153
+ } else {
154
+ // TODO: provide support for relative paths in assets as well
155
+ // relativise path
156
+ path = relative(event.path.replace(/\/[^/]+$/, "/"), joinURL("/", path));
157
+ if (!/^(?:\/|\.+\/)/.test(path)) {
158
+ path = `./${path}`;
159
+ }
160
+ }
161
+ }
162
+ ssrContext.head.push({ script: [{
163
+ tagPosition: "head",
164
+ tagPriority: -2,
165
+ type: "importmap",
166
+ innerHTML: JSON.stringify({ imports: { "#entry": path } })
167
+ }] }, headEntryOptions);
168
+ }
169
+ // 1. Preload payloads and app manifest
170
+ if (_PAYLOAD_EXTRACTION && !NO_SCRIPTS) {
171
+ ssrContext.head.push({ link: [NUXT_JSON_PAYLOADS ? {
172
+ rel: "preload",
173
+ as: "fetch",
174
+ crossorigin: "anonymous",
175
+ href: payloadURL
176
+ } : {
177
+ rel: "modulepreload",
178
+ crossorigin: "",
179
+ href: payloadURL
180
+ }] }, headEntryOptions);
181
+ }
182
+ if (isAppManifestEnabled && ssrContext["~preloadManifest"] && !NO_SCRIPTS) {
183
+ ssrContext.head.push({ link: [{
184
+ rel: "preload",
185
+ as: "fetch",
186
+ fetchpriority: "low",
187
+ crossorigin: "anonymous",
188
+ href: buildAssetsURL(`builds/meta/${ssrContext.runtimeConfig.app.buildId}.json`)
189
+ }] }, {
190
+ ...headEntryOptions,
191
+ tagPriority: "low"
192
+ });
193
+ }
194
+ // 2. Styles
195
+ if (inlinedStyles.length) {
196
+ ssrContext.head.push({ style: inlinedStyles });
197
+ }
198
+ const link = [];
199
+ for (const resource of Object.values(styles)) {
200
+ // Do not add links to resources that are inlined (vite v5+)
201
+ if (import.meta.dev && "inline" in getURLQuery(resource.file)) {
202
+ continue;
203
+ }
204
+ // Add CSS links in <head> for CSS files
205
+ // - in production
206
+ // - in dev mode when not rendering an island
207
+ link.push({
208
+ rel: "stylesheet",
209
+ href: renderer.rendererContext.buildAssetsURL(resource.file),
210
+ crossorigin: ""
211
+ });
212
+ }
213
+ if (link.length) {
214
+ ssrContext.head.push({ link }, headEntryOptions);
215
+ }
216
+ if (!NO_SCRIPTS) {
217
+ // 4. Resource Hints
218
+ ssrContext.head.push({ link: getPreloadLinks(ssrContext, renderer.rendererContext) }, headEntryOptions);
219
+ ssrContext.head.push({ link: getPrefetchLinks(ssrContext, renderer.rendererContext) }, headEntryOptions);
220
+ // 5. Payloads
221
+ ssrContext.head.push({ script: _PAYLOAD_EXTRACTION ? NUXT_JSON_PAYLOADS ? renderPayloadJsonScript({
222
+ ssrContext,
223
+ data: splitPayload(ssrContext).initial,
224
+ src: payloadURL
225
+ }) : renderPayloadScript({
226
+ ssrContext,
227
+ data: splitPayload(ssrContext).initial,
228
+ routeOptions,
229
+ src: payloadURL
230
+ }) : NUXT_JSON_PAYLOADS ? renderPayloadJsonScript({
231
+ ssrContext,
232
+ data: ssrContext.payload
233
+ }) : renderPayloadScript({
234
+ ssrContext,
235
+ data: ssrContext.payload,
236
+ routeOptions
237
+ }) }, {
238
+ ...headEntryOptions,
239
+ tagPosition: "bodyClose",
240
+ tagPriority: "high"
241
+ });
242
+ }
243
+ // 6. Scripts
244
+ if (!routeOptions.noScripts) {
245
+ const tagPosition = _PAYLOAD_EXTRACTION && !NUXT_JSON_PAYLOADS ? "bodyClose" : "head";
246
+ ssrContext.head.push({ script: Object.values(scripts).map((resource) => ({
247
+ type: resource.module ? "module" : null,
248
+ src: renderer.rendererContext.buildAssetsURL(resource.file),
249
+ defer: resource.module ? null : true,
250
+ tagPosition,
251
+ crossorigin: ""
252
+ })) }, headEntryOptions);
253
+ }
254
+ const { headTags, bodyTags, bodyTagsOpen, htmlAttrs, bodyAttrs } = await renderSSRHead(ssrContext.head, renderSSRHeadOptions);
255
+ // Create render context
256
+ const htmlContext = {
257
+ htmlAttrs: htmlAttrs ? [htmlAttrs] : [],
258
+ head: normalizeChunks([headTags]),
259
+ bodyAttrs: bodyAttrs ? [bodyAttrs] : [],
260
+ bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
261
+ body: [componentIslands ? replaceIslandTeleports(ssrContext, _rendered.html) : _rendered.html, APP_TELEPORT_OPEN_TAG + (HAS_APP_TELEPORTS ? joinTags([ssrContext.teleports?.[`#${appTeleportAttrs.id}`]]) : "") + APP_TELEPORT_CLOSE_TAG],
262
+ bodyAppend: [bodyTags]
263
+ };
264
+ // Allow hooking into the rendered result
265
+ await nitroApp.hooks.callHook("render:html", htmlContext, { event });
266
+ // Construct HTML response
267
+ return {
268
+ body: renderHTMLDocument(htmlContext),
269
+ statusCode: getResponseStatus(event),
270
+ statusMessage: getResponseStatusText(event),
271
+ headers: {
272
+ "content-type": "text/html;charset=utf-8",
273
+ "x-powered-by": "Nuxt"
274
+ }
275
+ };
276
+ });
277
+ function normalizeChunks(chunks) {
278
+ const result = [];
279
+ for (const _chunk of chunks) {
280
+ const chunk = _chunk?.trim();
281
+ if (chunk) {
282
+ result.push(chunk);
283
+ }
284
+ }
285
+ return result;
286
+ }
287
+ function joinTags(tags) {
288
+ return tags.join("");
289
+ }
290
+ function joinAttrs(chunks) {
291
+ if (chunks.length === 0) {
292
+ return "";
293
+ }
294
+ return " " + chunks.join(" ");
295
+ }
296
+ function renderHTMLDocument(html) {
297
+ 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>";
298
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default;
2
+ export default _default;
@@ -0,0 +1,7 @@
1
+ import { defineEventHandler, getRequestHeader } from "h3";
2
+ export default defineEventHandler((event) => {
3
+ if (getRequestHeader(event, "x-nuxt-no-ssr")) {
4
+ event.context.nuxt ||= {};
5
+ event.context.nuxt.noSSR = true;
6
+ }
7
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default;
2
+ export default _default;
@@ -0,0 +1,94 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { consola } from "consola";
3
+ import { stringify } from "devalue";
4
+ import { withTrailingSlash } from "ufo";
5
+ import { getContext } from "unctx";
6
+ import { captureRawStackTrace, parseRawStackTrace } from "errx";
7
+ import { isVNode } from "vue";
8
+ // @ts-expect-error virtual file
9
+ import { rootDir } from "#internal/dev-server-logs-options";
10
+ // @ts-expect-error virtual file
11
+ import { appId } from "#internal/nuxt.config.mjs";
12
+ const devReducers = {
13
+ VNode: (data) => isVNode(data) ? {
14
+ type: data.type,
15
+ props: data.props
16
+ } : undefined,
17
+ URL: (data) => data instanceof URL ? data.toString() : undefined
18
+ };
19
+ const asyncContext = getContext("nuxt-dev", {
20
+ asyncContext: true,
21
+ AsyncLocalStorage
22
+ });
23
+ export default (nitroApp) => {
24
+ const handler = nitroApp.h3App.handler;
25
+ nitroApp.h3App.handler = (event) => {
26
+ return asyncContext.callAsync({
27
+ logs: [],
28
+ event
29
+ }, () => handler(event));
30
+ };
31
+ onConsoleLog((_log) => {
32
+ const ctx = asyncContext.tryUse();
33
+ if (!ctx) {
34
+ return;
35
+ }
36
+ const rawStack = captureRawStackTrace();
37
+ if (!rawStack || rawStack.includes("runtime/vite-node.mjs")) {
38
+ return;
39
+ }
40
+ const trace = [];
41
+ let filename = "";
42
+ for (const entry of parseRawStackTrace(rawStack)) {
43
+ if (entry.source === import.meta.url) {
44
+ continue;
45
+ }
46
+ if (EXCLUDE_TRACE_RE.test(entry.source)) {
47
+ continue;
48
+ }
49
+ filename ||= entry.source.replace(withTrailingSlash(rootDir), "");
50
+ trace.push({
51
+ ...entry,
52
+ source: entry.source.startsWith("file://") ? entry.source.replace("file://", "") : entry.source
53
+ });
54
+ }
55
+ const log = {
56
+ ..._log,
57
+ filename,
58
+ stack: trace
59
+ };
60
+ // retain log to be include in the next render
61
+ ctx.logs.push(log);
62
+ });
63
+ nitroApp.hooks.hook("afterResponse", () => {
64
+ const ctx = asyncContext.tryUse();
65
+ if (!ctx) {
66
+ return;
67
+ }
68
+ return nitroApp.hooks.callHook("dev:ssr-logs", {
69
+ logs: ctx.logs,
70
+ path: ctx.event.path
71
+ });
72
+ });
73
+ // Pass any logs to the client
74
+ nitroApp.hooks.hook("render:html", (htmlContext) => {
75
+ const ctx = asyncContext.tryUse();
76
+ if (!ctx) {
77
+ return;
78
+ }
79
+ try {
80
+ const reducers = Object.assign(Object.create(null), devReducers, ctx.event.context["~payloadReducers"]);
81
+ htmlContext.bodyAppend.unshift(`<script type="application/json" data-nuxt-logs="${appId}">${stringify(ctx.logs, reducers)}<\/script>`);
82
+ } catch (e) {
83
+ const shortError = e instanceof Error && "toString" in e ? ` Received \`${e.toString()}\`.` : "";
84
+ 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/4.x/api/composables/use-nuxt-app#payload.`);
85
+ }
86
+ });
87
+ };
88
+ const EXCLUDE_TRACE_RE = /\/node_modules\/(?:.*\/)?(?:nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/|core\/runtime\/nitro/;
89
+ function onConsoleLog(callback) {
90
+ consola.addReporter({ log(logObj) {
91
+ callback(logObj);
92
+ } });
93
+ consola.wrapConsole();
94
+ }
@@ -0,0 +1,15 @@
1
+ import { escapeHtml } from "@vue/shared";
2
+ const _messages = {
3
+ "appName": "Nuxt",
4
+ "status": 500,
5
+ "statusText": "Internal server error",
6
+ "description": "This page is temporarily unavailable.",
7
+ "refresh": "Refresh this page"
8
+ };
9
+ export const template = (messages) => {
10
+ messages = {
11
+ ..._messages,
12
+ ...messages
13
+ };
14
+ 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\"><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><style>*,: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,h2{font-size:inherit;font-weight:inherit}h1,h2,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: }.grid{display:grid}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.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-2{padding-left:.5rem;padding-right:.5rem}.text-center{text-align:center}.text-\\[80px\\]{font-size:80px}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\\[\\#020420\\]{--un-text-opacity:1;color:rgb(2 4 32/var(--un-text-opacity))}.text-\\[\\#64748B\\]{--un-text-opacity:1;color:rgb(100 116 139/var(--un-text-opacity))}.font-semibold{font-weight:600}.leading-none{line-height:1}.tracking-wide{letter-spacing:.025em}.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}.tabular-nums{--un-numeric-spacing:tabular-nums;font-variant-numeric:var(--un-ordinal) var(--un-slashed-zero) var(--un-numeric-figure) var(--un-numeric-spacing) var(--un-numeric-fraction)}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media(prefers-color-scheme:dark){.dark\\:bg-\\[\\#020420\\]{--un-bg-opacity:1;background-color:rgb(2 4 32/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\\:text-\\[110px\\]{font-size:110px}.sm\\:text-3xl{font-size:1.875rem;line-height:2.25rem}}</style></head><body class=\"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide\"><div class=\"max-w-520px text-center\"><h1 class=\"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]\">" + escapeHtml(messages.status) + "</h1><h2 class=\"font-semibold mb-2 sm:text-3xl text-2xl\">" + escapeHtml(messages.statusText) + "</h2><p class=\"mb-4 px-2 text-[#64748B] text-md\">" + escapeHtml(messages.description) + "</p></div></body></html>";
15
+ };
@@ -0,0 +1,3 @@
1
+ import type { H3Event } from "h3";
2
+ import type { AppConfig } from "@nuxt/schema";
3
+ export declare function useAppConfig(event?: H3Event): AppConfig;