@nuxt/nitro-server-nightly 4.6.0-29833429.e2a0e5da → 4.6.0-29836601.d5e5f1bd

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.
@@ -1,7 +1,6 @@
1
1
  import { EventHandler, H3Event } from "h3";
2
2
  import { Nitro, NitroConfig, NitroDevEventHandler, NitroEventHandler, NitroOptions, NitroRouteConfig, NitroRouteRules, NitroRuntimeConfig } from "nitropack/types";
3
- import { LogObject } from "consola";
4
- import { NuxtIslandContext, NuxtIslandResponse, NuxtRenderChunkContext, NuxtRenderCloseContext, NuxtRenderHTMLContext, NuxtRenderRouteContext } from "#app/types";
3
+ import { DevServerLog, NuxtIslandContext, NuxtIslandResponse, NuxtRenderChunkContext, NuxtRenderCloseContext, NuxtRenderHTMLContext, NuxtRenderRouteContext } from "#app/types";
5
4
  import { NuxtRequestContext, NuxtRequestContext as NuxtRequestContext$1, RouteRuleConfigExtensions, RuntimeConfig, TracingChannelOptions } from "nuxt/schema";
6
5
  //#region src/augments.d.ts
7
6
  /** The channels this package's runtime forwards, alongside the Nuxt-owned ones. */
@@ -17,6 +16,22 @@ interface NitroTracingChannels {
17
16
  * @experimental Channel names, payload shapes, and option keys may change.
18
17
  */
19
18
  export type NuxtTracingChannelOptions = TracingChannelOptions;
19
+ /**
20
+ * Dev-only access to the SSR bundle's transformed modules, registered by the bundler that
21
+ * evaluates them in the Nitro process.
22
+ *
23
+ * @experimental
24
+ */
25
+ export interface SSRSourceMaps {
26
+ /** Transformed code of an SSR module as it was evaluated. */
27
+ getCode: (file: string) => string | undefined;
28
+ /** Position in generated code a source position was mapped from. */
29
+ getCompiledPosition?: (file: string, line: number, column?: number) => {
30
+ file: string;
31
+ line: number;
32
+ column: number;
33
+ } | undefined;
34
+ }
20
35
  declare global {
21
36
  interface ImportMeta {
22
37
  dev: boolean;
@@ -50,6 +65,15 @@ declare module "nitropack/types" {
50
65
  }
51
66
  }
52
67
  declare module "nitropack" {
68
+ interface NitroApp {
69
+ /**
70
+ * Only set in development, by bundlers that evaluate the SSR bundle within
71
+ * the Nitro process.
72
+ *
73
+ * @experimental
74
+ */
75
+ ssrSourceMaps?: SSRSourceMaps;
76
+ }
53
77
  interface NitroRuntimeConfig extends RuntimeConfig {}
54
78
  interface NitroRouteConfig extends RouteRuleConfigExtensions {}
55
79
  interface NitroRouteConfig {
@@ -61,7 +85,7 @@ declare module "nitropack" {
61
85
  }
62
86
  interface NitroRuntimeHooks {
63
87
  "dev:ssr-logs": (ctx: {
64
- logs: LogObject[];
88
+ logs: DevServerLog[];
65
89
  path: string;
66
90
  }) => void | Promise<void>;
67
91
  "render:html": (htmlContext: NuxtRenderHTMLContext, context: {
@@ -84,6 +108,15 @@ declare module "nitropack" {
84
108
  }
85
109
  }
86
110
  declare module "nitropack/types" {
111
+ interface NitroApp {
112
+ /**
113
+ * Only set in development, by bundlers that evaluate the SSR bundle within
114
+ * the Nitro process.
115
+ *
116
+ * @experimental
117
+ */
118
+ ssrSourceMaps?: SSRSourceMaps;
119
+ }
87
120
  interface NitroRuntimeConfig extends RuntimeConfig {}
88
121
  interface NitroRouteConfig extends RouteRuleConfigExtensions {}
89
122
  interface NitroRouteConfig {
@@ -95,7 +128,7 @@ declare module "nitropack/types" {
95
128
  }
96
129
  interface NitroRuntimeHooks {
97
130
  "dev:ssr-logs": (ctx: {
98
- logs: LogObject[];
131
+ logs: DevServerLog[];
99
132
  path: string;
100
133
  }) => void | Promise<void>;
101
134
  "render:html": (htmlContext: NuxtRenderHTMLContext, context: {
package/dist/index.mjs CHANGED
@@ -21,8 +21,9 @@ import { ImpoundPlugin } from "impound";
21
21
  import { resolveModulePath } from "exsolve";
22
22
  import { runtimeDependencies } from "nitropack/runtime/meta";
23
23
  import { matchesGlob } from "node:path";
24
+ import { isLoopbackAddress } from "nuxt/internal/dev/peer";
24
25
  //#region package.json
25
- var version = "4.6.0-29833429.e2a0e5da";
26
+ var version = "4.6.0-29836601.d5e5f1bd";
26
27
  //#endregion
27
28
  //#region src/utils.ts
28
29
  function toArray(value) {
@@ -105,26 +106,10 @@ const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
105
106
  "[::1]",
106
107
  "::1"
107
108
  ]);
108
- /**
109
- * Whether the connected peer is a loopback address.
110
- *
111
- * This inspects the TCP peer address rather than request metadata, so a
112
- * non-browser client cannot make itself look local by choosing its `Host`,
113
- * `Origin`, `Referer` or `Sec-Fetch-*` headers. `x-forwarded-for` is ignored on
114
- * purpose: only the address of the socket we are actually talking to counts.
115
- */
109
+ /** Whether the connected peer is a loopback address. */
116
110
  function isLoopbackPeer(event) {
117
111
  return isLoopbackAddress(getRequestIP(event));
118
112
  }
119
- function isLoopbackAddress(address) {
120
- if (!address) return false;
121
- let normalized = address.trim().toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
122
- const zoneIndex = normalized.indexOf("%");
123
- if (zoneIndex !== -1) normalized = normalized.slice(0, zoneIndex);
124
- if (normalized.startsWith("::ffff:")) normalized = normalized.slice(7);
125
- if (normalized === "::1") return true;
126
- return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(normalized);
127
- }
128
113
  /**
129
114
  * Header-based same-origin/allowed-host gate shared by dev-only handlers.
130
115
  *
@@ -421,8 +406,7 @@ ${[...references.map((ref) => renderReference(ref, typesDir)), ...declarations].
421
406
 
422
407
  import type { RouteRuleConfigExtensions, RuntimeConfig } from 'nuxt/schema'
423
408
  import type { H3Event } from 'h3'
424
- import type { LogObject } from 'consola'
425
- import type { NuxtIslandContext, NuxtIslandResponse, NuxtRenderChunkContext, NuxtRenderCloseContext, NuxtRenderHTMLContext, NuxtRenderRouteContext } from '#app/types'
409
+ import type { DevServerLog, NuxtIslandContext, NuxtIslandResponse, NuxtRenderChunkContext, NuxtRenderCloseContext, NuxtRenderHTMLContext, NuxtRenderRouteContext } from '#app/types'
426
410
 
427
411
  declare module 'nitropack' {
428
412
  interface NitroRuntimeConfig extends RuntimeConfig {}
@@ -444,7 +428,7 @@ declare module 'nitropack' {
444
428
  appLayout?: string | false
445
429
  }
446
430
  interface NitroRuntimeHooks {
447
- 'dev:ssr-logs': (ctx: { logs: LogObject[], path: string }) => void | Promise<void>
431
+ 'dev:ssr-logs': (ctx: { logs: DevServerLog[], path: string }) => void | Promise<void>
448
432
  'render:html': (htmlContext: NuxtRenderHTMLContext, context: { event: H3Event, streaming?: boolean }) => void | Promise<void>
449
433
  'render:html:chunk': (chunkContext: NuxtRenderChunkContext, context: { event: H3Event }) => void | Promise<void>
450
434
  'render:html:close': (closeContext: NuxtRenderCloseContext, context: { event: H3Event }) => void | Promise<void>
@@ -472,7 +456,7 @@ declare module 'nitropack/types' {
472
456
  appLayout?: string | false
473
457
  }
474
458
  interface NitroRuntimeHooks {
475
- 'dev:ssr-logs': (ctx: { logs: LogObject[], path: string }) => void | Promise<void>
459
+ 'dev:ssr-logs': (ctx: { logs: DevServerLog[], path: string }) => void | Promise<void>
476
460
  'render:html': (htmlContext: NuxtRenderHTMLContext, context: { event: H3Event, streaming?: boolean }) => void | Promise<void>
477
461
  'render:html:chunk': (chunkContext: NuxtRenderChunkContext, context: { event: H3Event }) => void | Promise<void>
478
462
  'render:html:close': (closeContext: NuxtRenderCloseContext, context: { event: H3Event }) => void | Promise<void>
@@ -545,11 +529,14 @@ async function bundle(nuxt) {
545
529
  baseURL: joinURL("/", asset.baseURL || "/", "**"),
546
530
  resolvedFrom: "your server directory and then your project root"
547
531
  });
532
+ if (nuxt.options.dev) {
533
+ nuxt.options.nitro.virtual = defu(nuxt.options.nitro.virtual, { "#internal/dev-server-logs-options": () => [`export const rootDir = ${JSON.stringify(nuxt.options.rootDir)};`, `export const srcDir = ${JSON.stringify(nuxt.options.srcDir)};`].join("\n") });
534
+ nuxt.options.nitro.externals = defu(nuxt.options.nitro.externals, { inline: [/#internal\/dev-server-logs-options/] });
535
+ addPlugin(resolve(nuxt.options.appDir, "plugins/dev-error-overlay.client"));
536
+ }
548
537
  if (nuxt.options.dev && nuxt.options.features.devLogs) {
549
538
  addPlugin(resolve(nuxt.options.appDir, "plugins/dev-server-logs"));
550
539
  nuxt.options.nitro.plugins.push(resolve(distDir, "runtime/plugins/dev-server-logs"));
551
- nuxt.options.nitro.externals = defu(nuxt.options.nitro.externals, { inline: [/#internal\/dev-server-logs-options/] });
552
- nuxt.options.nitro.virtual = defu(nuxt.options.nitro.virtual, { "#internal/dev-server-logs-options": () => `export const rootDir = ${JSON.stringify(nuxt.options.rootDir)};` });
553
540
  }
554
541
  const clientOnlyApp = !nuxt.options.ssr;
555
542
  if (nuxt.options.experimental.componentIslands) {
@@ -598,6 +585,7 @@ async function bundle(nuxt) {
598
585
  NUXT_PRERENDER_ERROR_PAGES: JSON.stringify(errorPages),
599
586
  NUXT_PRERENDER_NO_SSR_ROUTES: JSON.stringify(noSSRRoutes),
600
587
  NUXT_NO_SCRIPTS_PATTERNS: JSON.stringify(noScriptsPatterns),
588
+ NUXT_HAS_NO_SCRIPTS_ROUTES: String(noScriptsPatterns.length > 0),
601
589
  NUXT_PAGE_PATTERNS: JSON.stringify(pagePatterns),
602
590
  NUXT_EARLY_404: String(early404Patterns.length > 0),
603
591
  NUXT_PAGE_MATCHER: compilePageMatcher(early404Patterns),
@@ -673,7 +661,12 @@ async function bundle(nuxt) {
673
661
  virtual: {
674
662
  "#internal/nuxt.config.mjs": () => nuxt.vfs["#build/nuxt.config.mjs"] || "",
675
663
  "#internal/nuxt/app-config": () => nuxt.vfs["#build/app.config.mjs"]?.replace(/\/\*\* client \*\*\/[\s\S]*\/\*\* client-end \*\*\//, "") || "",
676
- "#internal/nuxt/nitro-config.mjs": () => [`export const NUXT_ASYNC_CONTEXT = ${!!nuxt.options.experimental.asyncContext}`, `export const NUXT_SHARED_DATA = ${!!nuxt.options.experimental.sharedPrerenderData}`].join("\n")
664
+ "#internal/nuxt/nitro-config.mjs": () => [
665
+ `export const NUXT_ERROR_CHANNEL = ${JSON.stringify(nuxt.options.devServer.errorChannel)}`,
666
+ `export const NUXT_DEV_LOGS = ${!!nuxt.options.features.devLogs}`,
667
+ `export const NUXT_ASYNC_CONTEXT = ${!!nuxt.options.experimental.asyncContext}`,
668
+ `export const NUXT_SHARED_DATA = ${!!nuxt.options.experimental.sharedPrerenderData}`
669
+ ].join("\n")
677
670
  },
678
671
  routeRules: {
679
672
  ...typeof nuxt.options.experimental.ssrStreaming === "object" && nuxt.options.experimental.ssrStreaming.enabled ? { "/**": { streaming: true } } : {},
@@ -1135,6 +1128,14 @@ async function bundle(nuxt) {
1135
1128
  const devMiddlewareHandler = dynamicEventHandler();
1136
1129
  nitro.options.devHandlers.unshift({ handler: devMiddlewareHandler });
1137
1130
  nitro.options.devHandlers.push(...nuxt.options.devServerHandlers);
1131
+ if (nuxt.options.dev) {
1132
+ nitro.options.plugins.push(resolve(distDir, "runtime/plugins/dev-errors"));
1133
+ nitro.options.handlers.unshift({
1134
+ route: joinURL(nuxt.options.devServer.errorChannel, "**"),
1135
+ lazy: true,
1136
+ handler: resolve(distDir, "runtime/handlers/error-channel")
1137
+ });
1138
+ }
1138
1139
  nitro.options.handlers.unshift({
1139
1140
  route: "/__nuxt_error",
1140
1141
  lazy: true,
@@ -0,0 +1,17 @@
1
+ import { useErrorChannel } from "../utils/error-channel.mjs";
2
+ import { defineEventHandler, getRequestIP, toWebRequest } from "h3";
3
+ import { isLoopbackAddress } from "nuxt/internal/dev/peer";
4
+ //#region src/runtime/handlers/error-channel.ts
5
+ /**
6
+ * Serves the live error channel: the SSE stream, report lookups and "open in editor".
7
+ *
8
+ * Trust follows the socket, since a request's origin headers are forgeable over a direct
9
+ * connection.
10
+ */
11
+ var error_channel_default = defineEventHandler(async (event) => {
12
+ const channel = await useErrorChannel();
13
+ const trusted = isLoopbackAddress(getRequestIP(event));
14
+ return await channel.fetchHandler(toWebRequest(event), { trusted }) ?? new Response("Not Found", { status: 404 });
15
+ });
16
+ //#endregion
17
+ export { error_channel_default as default };
@@ -1,17 +1,47 @@
1
1
  import { getFetchedRequestContext } from "../utils/event.mjs";
2
2
  import { isJsonRequest } from "../utils/error.mjs";
3
3
  import { applyPrerenderHints } from "../utils/prerender.mjs";
4
- import { generateErrorOverlayHTML } from "../utils/dev.mjs";
5
- import { appendResponseHeader, getResponseHeader, send, setResponseHeader, setResponseHeaders, setResponseStatus } from "h3";
4
+ import { appendResponseHeader, getResponseHeader, isError, send, setResponseHeader, setResponseHeaders, setResponseStatus } from "h3";
6
5
  import { useNitroApp, useRuntimeConfig } from "nitropack/runtime";
7
6
  import { joinURL, withQuery, withoutBase } from "ufo";
8
7
  //#region src/runtime/handlers/error.ts
9
8
  var error_default = async function errorhandler(error, event, { defaultHandler }) {
10
- if (event.handled || isJsonRequest(event)) return;
11
- const defaultRes = await defaultHandler(error, event, { json: true });
9
+ if (event.handled) return;
10
+ const isRenderingError = !!(event.context.nuxt?.["~rendering-error"] || getFetchedRequestContext(event)?.["~rendering-error"]);
11
+ let report;
12
+ let errorCause;
13
+ if (import.meta.dev) {
14
+ const errorChannel = await import("../utils/error-channel.mjs");
15
+ const isHTTPError = isError(error);
16
+ report = !error.unhandled && isHTTPError && (error.statusCode || 500) < 500 && !(THROWN_VALUE in error) ? void 0 : await errorChannel.createErrorReport(error, event).catch(() => void 0);
17
+ errorCause = errorChannel.serializeErrorCause(error.cause);
18
+ if (report && !isRenderingError && !import.meta.test) await errorChannel.publishErrorReport(report, event).catch(() => {});
19
+ if (report && !isRenderingError && !errorChannel.shouldForwardReports() && (error.unhandled ?? !isHTTPError)) {
20
+ const rendered = await errorChannel.renderErrorAnsi(report).catch(() => void 0);
21
+ if (rendered) console.log(`[request error] [${event.method}] ${event.path}\n\n${rendered}`);
22
+ else console.error(`[request error] [${event.method}] ${event.path}\n\n`, error);
23
+ }
24
+ }
25
+ const stacks = import.meta.dev ? snapshotStacks(error) : void 0;
26
+ if (isJsonRequest(event)) {
27
+ if (!report) return;
28
+ const { headers, status, statusText, body } = await defaultHandler(error, event, {
29
+ json: true,
30
+ silent: true
31
+ });
32
+ stacks?.restore();
33
+ setResponseHeaders(event, headers);
34
+ appendVary(event, "accept, sec-fetch-mode");
35
+ setResponseStatus(event, status, statusText);
36
+ return send(event, typeof body === "string" ? body : JSON.stringify(body, null, 2));
37
+ }
38
+ const defaultRes = await defaultHandler(error, event, {
39
+ json: true,
40
+ silent: import.meta.dev && !!report
41
+ });
42
+ stacks?.restore();
12
43
  if (import.meta.prerender) applyPrerenderHints(event);
13
- const status = error.status || error.statusCode || 500;
14
- if (status === 404 && defaultRes.status === 302) {
44
+ if ((error.status || error.statusCode || 500) === 404 && defaultRes.status === 302) {
15
45
  setResponseHeaders(event, defaultRes.headers);
16
46
  appendVary(event, "accept, sec-fetch-mode");
17
47
  setResponseStatus(event, defaultRes.status, defaultRes.statusText);
@@ -24,12 +54,10 @@ var error_default = async function errorhandler(error, event, { defaultHandler }
24
54
  errorObject.message = error.unhandled ? errorObject.message || "Server Error" : error.message || errorObject.message || "Server Error";
25
55
  if (!error.unhandled) errorObject.data ||= error.data;
26
56
  errorObject.statusText ||= error.statusText || error.statusMessage;
27
- const errorCause = import.meta.dev ? serializeErrorCause(error.cause) : void 0;
28
57
  delete defaultRes.headers["content-type"];
29
58
  delete defaultRes.headers["content-security-policy"];
30
59
  setResponseHeaders(event, defaultRes.headers);
31
60
  appendVary(event, "accept, sec-fetch-mode");
32
- const isRenderingError = !!(event.context.nuxt?.["~rendering-error"] || getFetchedRequestContext(event)?.["~rendering-error"]);
33
61
  if (!isRenderingError) event.context.nuxt = {
34
62
  ...event.context.nuxt,
35
63
  "~rendering-error": true
@@ -44,13 +72,20 @@ var error_default = async function errorhandler(error, event, { defaultHandler }
44
72
  }).catch(() => null);
45
73
  if (event.handled) return;
46
74
  if (!res) {
75
+ setResponseHeader(event, "Content-Type", "text/html;charset=UTF-8");
76
+ if (import.meta.dev && isRenderingError) setResponseHeader(event, ERROR_PAGE_HEADER, "1");
77
+ else if (import.meta.dev && report) {
78
+ const { renderErrorPage } = await import("../utils/error-channel.mjs");
79
+ const body = await renderErrorPage(report, event).catch(() => void 0);
80
+ if (body) return send(event, body);
81
+ }
47
82
  const { template } = await import("../templates/error-500.mjs");
48
83
  if (import.meta.dev) errorObject.description = errorObject.message;
49
- setResponseHeader(event, "Content-Type", "text/html;charset=UTF-8");
50
84
  return send(event, template(errorObject));
51
85
  }
52
- const html = await res.text();
86
+ let html = await res.text();
53
87
  for (const [header, value] of res.headers.entries()) {
88
+ if (header === ERROR_PAGE_HEADER) continue;
54
89
  if (header === "set-cookie" || header === "x-nitro-prerender") {
55
90
  appendResponseHeader(event, header, value);
56
91
  continue;
@@ -58,12 +93,39 @@ var error_default = async function errorhandler(error, event, { defaultHandler }
58
93
  setResponseHeader(event, header, value);
59
94
  }
60
95
  setResponseStatus(event, res.status && res.status !== 200 ? res.status : defaultRes.status, res.statusText || defaultRes.statusText);
61
- if (import.meta.dev && !import.meta.test && typeof html === "string") {
62
- const prettyResponse = await defaultHandler(error, event, { json: false });
63
- if (typeof prettyResponse.body === "string") return send(event, html.replace("</body>", `${generateErrorOverlayHTML(prettyResponse.body, { startMinimized: 300 <= status && status < 500 })}</body>`));
96
+ if (import.meta.dev && !import.meta.test && report && typeof html === "string") {
97
+ const { renderErrorPage, withErrorOverlay } = await import("../utils/error-channel.mjs");
98
+ try {
99
+ html = res.headers.has(ERROR_PAGE_HEADER) ? await renderErrorPage(report, event) : await withErrorOverlay(html, report, {
100
+ startMinimized: true,
101
+ event
102
+ });
103
+ } catch {}
64
104
  }
65
105
  return send(event, html);
66
106
  };
107
+ /** The stacks of an error and its causes as raised, before Nitro rewrites them. */
108
+ function snapshotStacks(error) {
109
+ const stacks = [];
110
+ const seen = /* @__PURE__ */ new Set();
111
+ for (let current = error; current instanceof Error && !seen.has(current); current = current.cause) {
112
+ seen.add(current);
113
+ stacks.push([current, current.stack]);
114
+ }
115
+ return { restore() {
116
+ for (const [target, stack] of stacks) if (target.stack !== stack) try {
117
+ Object.defineProperty(target, "stack", {
118
+ value: stack,
119
+ writable: true,
120
+ configurable: true
121
+ });
122
+ } catch {}
123
+ } };
124
+ }
125
+ /** Set on an error created from a thrown value that was not an `Error`. */
126
+ const THROWN_VALUE = Symbol.for("nuxt:dev:thrown");
127
+ /** Set when the app's own error page could not render. */
128
+ const ERROR_PAGE_HEADER = "x-nuxt-error-page";
67
129
  /**
68
130
  * Add `value`'s tokens to the response `vary` header, keeping any already
69
131
  * present. `*` absorbs everything else, since it means the response varies on
@@ -85,19 +147,5 @@ function appendVary(event, value) {
85
147
  function parseVary(value) {
86
148
  return (Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : []).map((token) => token.trim().toLowerCase()).filter(Boolean);
87
149
  }
88
- function serializeErrorCause(cause, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
89
- if (depth >= 10 || cause instanceof Error && seen.has(cause)) return;
90
- if (cause instanceof Error) {
91
- seen.add(cause);
92
- const nestedCause = serializeErrorCause(cause.cause, depth + 1, seen);
93
- return {
94
- name: cause.name,
95
- message: cause.message,
96
- ...cause.stack && { stack: cause.stack },
97
- ...nestedCause !== void 0 && { cause: nestedCause }
98
- };
99
- }
100
- if (cause === null || typeof cause === "string" || typeof cause === "number" || typeof cause === "boolean") return cause;
101
- }
102
150
  //#endregion
103
151
  export { error_default as default };
@@ -3,8 +3,8 @@ import { applyPrerenderHints } from "../utils/prerender.mjs";
3
3
  import { rendererInstance } from "../utils/renderer/options.mjs";
4
4
  import { setResponseHeader } from "h3";
5
5
  import { defineRenderHandler } from "nitropack/runtime";
6
- import { AsyncLocalStorage } from "node:async_hooks";
7
6
  import { NUXT_ASYNC_CONTEXT } from "#internal/nuxt/nitro-config.mjs";
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { createNuxtRenderer } from "nuxt/internal/renderer";
9
9
  //#region src/runtime/handlers/renderer.ts
10
10
  if (NUXT_ASYNC_CONTEXT && !("AsyncLocalStorage" in globalThis)) globalThis.AsyncLocalStorage = AsyncLocalStorage;
@@ -1,3 +1,3 @@
1
- import "h3";
1
+ import { createError as createError$1 } from "h3";
2
2
  export * from "h3";
3
- export {};
3
+ export { createError$1 as createError };
@@ -1,5 +1,32 @@
1
- import "../../../nitro-server/src/h3.mjs";
1
+ import { createError as createError$1 } from "../../../nitro-server/src/h3.mjs";
2
2
  //#region ../nuxt/src/app/error.ts
3
3
  const NUXT_ERROR_SIGNATURE = "__nuxt_error";
4
+ /** @since 3.0.0 */
5
+ const isNuxtError = (error) => !!error && typeof error === "object" && "__nuxt_error" in error;
6
+ /** @since 3.0.0 */
7
+ const createError = (error) => {
8
+ if (isNuxtError(error)) return error;
9
+ if (typeof error !== "string" && error?.statusText) error.message ??= error.statusText;
10
+ const nuxtError = createError$1(error ?? {});
11
+ Object.defineProperty(nuxtError, NUXT_ERROR_SIGNATURE, {
12
+ value: true,
13
+ configurable: false,
14
+ writable: false
15
+ });
16
+ Object.defineProperty(nuxtError, "status", {
17
+ get: () => nuxtError.statusCode,
18
+ configurable: true
19
+ });
20
+ Object.defineProperty(nuxtError, "statusText", {
21
+ get: () => nuxtError.statusMessage,
22
+ configurable: true
23
+ });
24
+ return nuxtError;
25
+ };
26
+ /** Set in development on an error created from a thrown value that was not an `Error`. */
27
+ const THROWN_VALUE = Symbol.for("nuxt:dev:thrown");
28
+ /** Set in development to where the app was when it threw. */
29
+ const THROWN_CONTEXT = Symbol.for("nuxt:dev:context");
30
+ import.meta.dev;
4
31
  //#endregion
5
- export { NUXT_ERROR_SIGNATURE };
32
+ export { NUXT_ERROR_SIGNATURE, THROWN_CONTEXT, THROWN_VALUE, createError, isNuxtError };
@@ -0,0 +1,62 @@
1
+ import { publishDevLog, useErrorChannel } from "../utils/error-channel.mjs";
2
+ import { NUXT_DEV_LOGS } from "#internal/nuxt/nitro-config.mjs";
3
+ import { formatWithOptions } from "node:util";
4
+ import { consola } from "consola";
5
+ //#region src/runtime/plugins/dev-errors.ts
6
+ /** Opens the error channel before anything requests a page. */
7
+ var dev_errors_default = (_nitroApp) => {
8
+ useErrorChannel().catch(() => {});
9
+ if (NUXT_DEV_LOGS) streamLogsToChannel();
10
+ };
11
+ /** Mirror what the server logs onto the error channel. */
12
+ function streamLogsToChannel() {
13
+ let publishing = false;
14
+ consola.addReporter({ log(logObject) {
15
+ if (publishing) return;
16
+ publishing = true;
17
+ try {
18
+ publishDevLog(toLogEntry(logObject)).catch(() => {});
19
+ } finally {
20
+ publishing = false;
21
+ }
22
+ } });
23
+ }
24
+ function toLogEntry(logObject) {
25
+ const args = logObject.args ?? [];
26
+ const message = formatWithOptions({
27
+ colors: false,
28
+ depth: 2
29
+ }, ...args);
30
+ return {
31
+ level: toLogLevel(logObject),
32
+ text: logObject.tag ? `[${logObject.tag}] ${message}` : message,
33
+ timestamp: logObject.date ? new Date(logObject.date).getTime() : void 0
34
+ };
35
+ }
36
+ const LOG_LEVELS = {
37
+ trace: "trace",
38
+ debug: "debug",
39
+ verbose: "debug",
40
+ info: "info",
41
+ log: "log",
42
+ warn: "warn",
43
+ error: "error",
44
+ fail: "error",
45
+ fatal: "fatal"
46
+ };
47
+ /** Fallback for consola types whose names say nothing about severity. */
48
+ const LOG_LEVELS_BY_SEVERITY = [
49
+ "error",
50
+ "warn",
51
+ "log",
52
+ "info",
53
+ "debug",
54
+ "trace"
55
+ ];
56
+ function toLogLevel(logObject) {
57
+ if (LOG_LEVELS[logObject.type]) return LOG_LEVELS[logObject.type];
58
+ const severity = Math.round(logObject.level);
59
+ return LOG_LEVELS_BY_SEVERITY[Math.max(0, Math.min(severity, LOG_LEVELS_BY_SEVERITY.length - 1))] ?? "log";
60
+ }
61
+ //#endregion
62
+ export { dev_errors_default as default };
@@ -1,5 +1,6 @@
1
1
  import { serverDiagnostics } from "../diagnostics.mjs";
2
2
  import { withTrailingSlash } from "ufo";
3
+ import { rootDir } from "#internal/dev-server-logs-options";
3
4
  import { appId } from "#internal/nuxt.config.mjs";
4
5
  import { AsyncLocalStorage } from "node:async_hooks";
5
6
  import { consola } from "consola";
@@ -7,7 +8,6 @@ import { stringify } from "devalue";
7
8
  import { getContext } from "unctx";
8
9
  import { captureRawStackTrace, parseRawStackTrace } from "errx";
9
10
  import { isVNode } from "vue";
10
- import { rootDir } from "#internal/dev-server-logs-options";
11
11
  //#region src/runtime/plugins/dev-server-logs.ts
12
12
  const devReducers = {
13
13
  VNode: (data) => isVNode(data) ? {
@@ -2,7 +2,7 @@ import { NUXT_ERROR_SIGNATURE } from "./nuxt/src/app/error.mjs";
2
2
  import { toPortableEvent } from "./utils/event.mjs";
3
3
  import { createError as createError$1, deleteCookie, getCookie, getQuery as getQuery$1, getRequestHeader as getRequestHeader$1, getRequestHeaders as getRequestHeaders$1, getRequestURL, readBody, setCookie, setResponseHeader, setResponseHeaders, setResponseStatus } from "h3";
4
4
  import { getRouteRules as getRouteRules$1, useRuntimeConfig as useRuntimeConfig$1 } from "nitropack/runtime";
5
- import { toNuxtRequestEvent } from "nuxt/internal/server-default";
5
+ import { clearSession, deriveSecret, getSession, toNuxtRequestEvent, updateSession, useSession } from "nuxt/internal/server-default";
6
6
  //#region src/runtime/server.ts
7
7
  /**
8
8
  * The `nuxt/server` implementations for a nitropack v2 build, registered as
@@ -130,4 +130,4 @@ function useRuntimeConfig(event) {
130
130
  return useRuntimeConfig$1(event);
131
131
  }
132
132
  //#endregion
133
- export { createError, defineEventHandler, deleteCookie, getCookie, getQuery, getRequestHeader, getRequestHeaders, getRequestURL, getRouteRules, isNuxtError, readBody, sendRedirect, setCookie, setResponseHeader, setResponseHeaders, setResponseStatus, toNuxtRequestEvent, useRuntimeConfig };
133
+ export { clearSession, createError, defineEventHandler, deleteCookie, deriveSecret, getCookie, getQuery, getRequestHeader, getRequestHeaders, getRequestURL, getRouteRules, getSession, isNuxtError, readBody, sendRedirect, setCookie, setResponseHeader, setResponseHeaders, setResponseStatus, toNuxtRequestEvent, updateSession, useRuntimeConfig, useSession };
@@ -12,7 +12,7 @@ const template = (messages) => {
12
12
  ..._messages,
13
13
  ...messages
14
14
  };
15
- 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,minimum-scale=1\" name=\"viewport\"><style>*,:after,:before{box-sizing:border-box;border-style:solid;border-width:0;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:\"\"}html{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}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 #0000;--un-ring-shadow:0 0 #0000;--un-shadow-inset:;--un-shadow:0 0 #0000;--un-ring-inset:;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:#93c5fd80;--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 (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
+ 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,minimum-scale=1\" name=\"viewport\"><style>*,:after,:before{box-sizing:border-box;border-style:solid;border-width:0;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:\"\"}html{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}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 #0000;--un-ring-shadow:0 0 #0000;--un-shadow-inset:;--un-shadow:0 0 #0000;--un-ring-inset:;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:#93c5fd80;--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-\\[56px\\]{font-size:56px}.text-2xl{font-size:1.5rem;line-height:2rem}.text-neutral-500{--un-text-opacity:1;color:rgb(115 115 115/var(--un-text-opacity))}.text-neutral-950{--un-text-opacity:1;color:rgb(10 10 10/var(--un-text-opacity))}.font-medium{font-weight:500}.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-neutral-950{--un-bg-opacity:1;background-color:rgb(10 10 10/var(--un-bg-opacity))}.dark\\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (width>=640px){.sm\\:text-\\[72px\\]{font-size:72px}.sm\\:text-3xl{font-size:1.875rem;line-height:2.25rem}}</style></head><body class=\"antialiased bg-white dark:bg-neutral-950 dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-neutral-950 tracking-wide\"><div class=\"max-w-520px text-center\"><h1 class=\"font-medium leading-none mb-4 sm:text-[72px] tabular-nums text-[56px]\">" + 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-md text-neutral-500\">" + escapeHtml(messages.description) + "</p></div></body></html>";
16
16
  };
17
17
  //#endregion
18
18
  export { template };
@@ -1,9 +1,9 @@
1
+ import { dirname, join, resolve } from "node:path";
1
2
  import crypto from "node:crypto";
2
3
  import { mkdir, rename, unlink, writeFile } from "node:fs/promises";
3
- import { dirname, join, resolve } from "node:path";
4
+ import flru from "flru";
4
5
  import { defineDriver } from "unstorage";
5
6
  import fsDriver from "unstorage/drivers/fs-lite";
6
- import lruCache from "unstorage/drivers/lru-cache";
7
7
  //#region src/runtime/utils/cache-driver.mjs
8
8
  /**
9
9
  * @param {string} item
@@ -35,19 +35,20 @@ var cache_driver_default = defineDriver(
35
35
  */
36
36
  (opts) => {
37
37
  const fs = fsDriver({ base: opts.base });
38
- const lru = lruCache({ max: 1e3 });
38
+ /** flru keeps an active and a stale half, so up to 2x `max` entries are retained. */
39
+ const lru = flru(500);
39
40
  const base = resolve(opts.base || ".");
40
41
  return {
41
42
  ...fs,
42
- async setItem(key, value, opts) {
43
+ async setItem(key, value) {
43
44
  await atomicWrite(join(base, normalizeFsKey(key)), value);
44
- await lru.setItem?.(key, value, opts);
45
+ lru.set(key, value);
45
46
  },
46
47
  async hasItem(key, opts) {
47
- return await lru.hasItem(key, opts) || await fs.hasItem(normalizeFsKey(key), opts);
48
+ return lru.has(key) || await fs.hasItem(normalizeFsKey(key), opts);
48
49
  },
49
50
  async getItem(key, opts) {
50
- return await lru.getItem(key, opts) || await fs.getItem(normalizeFsKey(key), opts);
51
+ return lru.get(key) || await fs.getItem(normalizeFsKey(key), opts);
51
52
  }
52
53
  };
53
54
  }
@@ -1,6 +1,6 @@
1
1
  import { useStorage } from "nitropack/runtime";
2
- import { AsyncLocalStorage } from "node:async_hooks";
3
2
  import { NUXT_SHARED_DATA } from "#internal/nuxt/nitro-config.mjs";
3
+ import { AsyncLocalStorage } from "node:async_hooks";
4
4
  //#region src/runtime/utils/cache.ts
5
5
  /**
6
6
  * Stack of URLs currently rendering in the active async context (oldest first).